[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
|
* 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
|
||||||
*/
|
*/
|
||||||
|
|||||||
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