[orx-compositor] Add BufferMultisample support (#236)
Co-authored-by: Yvee1 <stevenvdb@live.nl>
This commit is contained in:
@@ -33,7 +33,7 @@ fun RenderTarget.deepDestroy() {
|
||||
* A single layer representation
|
||||
*/
|
||||
@Description("Layer")
|
||||
open class Layer internal constructor() {
|
||||
open class Layer internal constructor(val bufferMultisample: BufferMultisample = BufferMultisample.Disabled) {
|
||||
var copyLayers: List<Layer> = listOf()
|
||||
var sourceOut = SourceOut()
|
||||
var sourceIn = SourceIn()
|
||||
@@ -43,7 +43,8 @@ open class Layer internal constructor() {
|
||||
var blendFilter: Pair<Filter, Filter.() -> Unit>? = null
|
||||
val postFilters: MutableList<Pair<Filter, Filter.() -> Unit>> = mutableListOf()
|
||||
var colorType = ColorType.UINT8
|
||||
var accumulation: ColorBuffer? = null
|
||||
private var resolvedColorBuffer: ColorBuffer? = null
|
||||
private var activeRenderTargetColorBuffer: ColorBuffer? = null
|
||||
|
||||
@BooleanParameter("enabled")
|
||||
var enabled = true
|
||||
@@ -68,14 +69,8 @@ open class Layer internal constructor() {
|
||||
|
||||
val activeRenderTarget = RenderTarget.active
|
||||
|
||||
accumulation = if (activeRenderTarget !is ProgramRenderTarget) {
|
||||
activeRenderTarget.colorBuffer(0)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
if (shouldCreateLayerTarget(activeRenderTarget)) {
|
||||
createLayerTarget(activeRenderTarget, drawer)
|
||||
createLayerTarget(activeRenderTarget, drawer, bufferMultisample)
|
||||
}
|
||||
|
||||
layerTarget?.let { target ->
|
||||
@@ -87,7 +82,12 @@ open class Layer internal constructor() {
|
||||
}
|
||||
|
||||
it.layerTarget?.let { copyTarget ->
|
||||
drawer.image(copyTarget.colorBuffer(0))
|
||||
if (it.bufferMultisample == BufferMultisample.Disabled) {
|
||||
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 {
|
||||
if (it.shouldCreateLayerTarget(activeRenderTarget)) {
|
||||
it.createLayerTarget(activeRenderTarget, drawer)
|
||||
it.createLayerTarget(activeRenderTarget, drawer, it.bufferMultisample)
|
||||
}
|
||||
|
||||
it.layerTarget?.let { maskRt ->
|
||||
@@ -125,11 +125,9 @@ open class Layer internal constructor() {
|
||||
}
|
||||
|
||||
if (postFilters.size > 0) {
|
||||
val sizeMismatch = if (postBufferCache.isNotEmpty()) {
|
||||
postBufferCache[0].width != activeRenderTarget.width || postBufferCache[0].height != activeRenderTarget.height
|
||||
} else {
|
||||
false
|
||||
}
|
||||
val sizeMismatch = postBufferCache.isNotEmpty()
|
||||
&& (postBufferCache[0].width != activeRenderTarget.width
|
||||
|| postBufferCache[0].height != activeRenderTarget.height)
|
||||
|
||||
if (sizeMismatch) {
|
||||
postBufferCache.forEach { it.destroy() }
|
||||
@@ -137,8 +135,14 @@ open class Layer internal constructor() {
|
||||
}
|
||||
|
||||
if (postBufferCache.isEmpty()) {
|
||||
postBufferCache += persistent { colorBuffer(activeRenderTarget.width, activeRenderTarget.height, type = colorType) }
|
||||
postBufferCache += persistent { colorBuffer(activeRenderTarget.width, activeRenderTarget.height, type = colorType) }
|
||||
postBufferCache += persistent {
|
||||
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 {
|
||||
val maskFilter = if (invertMask) sourceOut else sourceIn
|
||||
|
||||
maskFilter.apply(arrayOf(layerPost, it.layerTarget!!.colorBuffer(0)), layerPost)
|
||||
}
|
||||
|
||||
@@ -165,27 +168,56 @@ open class Layer internal constructor() {
|
||||
drawer.ortho()
|
||||
drawer.view = Matrix44.IDENTITY
|
||||
drawer.model = Matrix44.IDENTITY
|
||||
drawer.image(layerPost, layerPost.bounds, drawer.bounds)
|
||||
if (bufferMultisample == BufferMultisample.Disabled) {
|
||||
drawer.image(layerPost, layerPost.bounds, drawer.bounds)
|
||||
} else {
|
||||
layerPost.copyTo(resolvedColorBuffer!!)
|
||||
drawer.image(resolvedColorBuffer!!, layerPost.bounds, drawer.bounds)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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 {
|
||||
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 = renderTarget(activeRenderTarget.width, activeRenderTarget.height) {
|
||||
layerTarget = renderTarget(activeRenderTarget.width, activeRenderTarget.height,
|
||||
activeRenderTarget.contentScale, bufferMultisample) {
|
||||
colorBuffer(type = colorType)
|
||||
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 {
|
||||
drawer.withTarget(it) {
|
||||
drawer.clear(ColorRGBa.TRANSPARENT)
|
||||
@@ -203,6 +235,15 @@ fun Layer.layer(function: Layer.() -> Unit): 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
|
||||
*/
|
||||
|
||||
50
orx-compositor/src/demo/kotlin/DemoCompositor02.kt
Normal file
50
orx-compositor/src/demo/kotlin/DemoCompositor02.kt
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user