[orx-dnk3] Add segmentContourRenderer
This commit is contained in:
@@ -14,7 +14,7 @@ buildscript {
|
|||||||
apply plugin: 'org.jetbrains.dokka'
|
apply plugin: 'org.jetbrains.dokka'
|
||||||
|
|
||||||
project.ext {
|
project.ext {
|
||||||
openrndrVersion = "0.3.43-rc.11"
|
openrndrVersion = "0.3.43-rc.12"
|
||||||
kotlinVersion = "1.3.72"
|
kotlinVersion = "1.3.72"
|
||||||
spekVersion = "2.0.10"
|
spekVersion = "2.0.10"
|
||||||
libfreenectVersion = "0.5.7-1.5.3"
|
libfreenectVersion = "0.5.7-1.5.3"
|
||||||
|
|||||||
49
orx-dnk3/src/demo/kotlin/DemoSegmentContours01.kt
Normal file
49
orx-dnk3/src/demo/kotlin/DemoSegmentContours01.kt
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.draw.BufferMultisample
|
||||||
|
import org.openrndr.extensions.SingleScreenshot
|
||||||
|
import org.openrndr.extra.dnk3.*
|
||||||
|
import org.openrndr.extra.dnk3.gltf.buildSceneNodes
|
||||||
|
import org.openrndr.extra.dnk3.gltf.loadGltfFromFile
|
||||||
|
import org.openrndr.extra.dnk3.renderers.segmentContourRenderer
|
||||||
|
import org.openrndr.extras.camera.Orbital
|
||||||
|
import org.openrndr.math.Vector3
|
||||||
|
import org.openrndr.math.mod_
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
width = 1280
|
||||||
|
height = 720
|
||||||
|
//multisample = WindowMultisample.SampleCount(8)
|
||||||
|
}
|
||||||
|
|
||||||
|
program {
|
||||||
|
if (System.getProperty("takeScreenshot") == "true") {
|
||||||
|
extend(SingleScreenshot()) {
|
||||||
|
this.outputFile = System.getProperty("screenshotPath")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val gltf = loadGltfFromFile(File("demo-data/gltf-models/fox/Fox.glb"))
|
||||||
|
val scene = Scene(SceneNode())
|
||||||
|
|
||||||
|
val sceneData = gltf.buildSceneNodes()
|
||||||
|
scene.root.children.addAll(sceneData.scenes.first())
|
||||||
|
|
||||||
|
// -- create a renderer, try it with BufferMultisample.SampleCount(8) for better results
|
||||||
|
val renderer = segmentContourRenderer(BufferMultisample.Disabled)
|
||||||
|
extend(Orbital()) {
|
||||||
|
far = 500.0
|
||||||
|
lookAt = Vector3(0.0, 40.0, 0.0)
|
||||||
|
eye = Vector3(150.0, 40.0, 200.0)
|
||||||
|
fov = 40.0
|
||||||
|
}
|
||||||
|
|
||||||
|
extend {
|
||||||
|
sceneData.animations[2].applyToTargets(seconds.mod_(sceneData.animations[2].duration))
|
||||||
|
drawer.clear(ColorRGBa.PINK)
|
||||||
|
renderer.draw(drawer, scene)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,18 +15,26 @@ enum class FacetType(val shaderFacet: String) {
|
|||||||
EMISSIVE("f_emission"),
|
EMISSIVE("f_emission"),
|
||||||
AMBIENT("f_ambient"),
|
AMBIENT("f_ambient"),
|
||||||
OCCLUSION("f_occlusion"),
|
OCCLUSION("f_occlusion"),
|
||||||
|
FRAGMENT_ID("f_fragmentID"),
|
||||||
COLOR("m_color"),
|
COLOR("m_color"),
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class FacetCombiner(val facets: Set<FacetType>, val targetOutput: String) {
|
abstract class FacetCombiner(val facets: Set<FacetType>, val targetOutput: String) {
|
||||||
abstract fun generateShader(): String
|
abstract fun generateShader(): String
|
||||||
|
override fun toString(): String {
|
||||||
|
return "FacetCombiner(facets=$facets, targetOutput='$targetOutput')"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ColorBufferFacetCombiner(facets: Set<FacetType>,
|
abstract class ColorBufferFacetCombiner(facets: Set<FacetType>,
|
||||||
targetOutput: String,
|
targetOutput: String,
|
||||||
val format: ColorFormat,
|
val format: ColorFormat,
|
||||||
val type: ColorType,
|
val type: ColorType,
|
||||||
val blendMode: BlendMode = BlendMode.BLEND) : FacetCombiner(facets, targetOutput)
|
val blendMode: BlendMode = BlendMode.BLEND) : FacetCombiner(facets, targetOutput) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class MomentsFacet : ColorBufferFacetCombiner(setOf(FacetType.WORLD_POSITION), "moments", ColorFormat.RG, ColorType.FLOAT16) {
|
class MomentsFacet : ColorBufferFacetCombiner(setOf(FacetType.WORLD_POSITION), "moments", ColorFormat.RG, ColorType.FLOAT16) {
|
||||||
override fun generateShader(): String {
|
override fun generateShader(): String {
|
||||||
@@ -111,6 +119,12 @@ class ClipPositionFacet : ColorBufferFacetCombiner(setOf(FacetType.CLIP_POSITION
|
|||||||
override fun generateShader() = "o_$targetOutput.rgb = gl_FragCoord.xyz;"
|
override fun generateShader() = "o_$targetOutput.rgb = gl_FragCoord.xyz;"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FragmentIDFacet: ColorBufferFacetCombiner(setOf(FacetType.FRAGMENT_ID), "fragmentID", ColorFormat.R, ColorType.UINT16_INT) {
|
||||||
|
override fun generateShader(): String {
|
||||||
|
return "o_$targetOutput = f_fragmentID;"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class LDRColorFacet : ColorBufferFacetCombiner(setOf(FacetType.DIFFUSE, FacetType.SPECULAR), "color", ColorFormat.RGBa, ColorType.UINT8) {
|
class LDRColorFacet : ColorBufferFacetCombiner(setOf(FacetType.DIFFUSE, FacetType.SPECULAR), "color", ColorFormat.RGBa, ColorType.UINT8) {
|
||||||
override fun generateShader() = """
|
override fun generateShader() = """
|
||||||
vec3 finalColor = (max(vec3(0.0), f_diffuse.rgb) + max(vec3(0.0),f_specular.rgb) + max(vec3(0.0), f_emission.rgb)) * (1.0 - f_fog.a) + f_fog.rgb * f_fog.a;
|
vec3 finalColor = (max(vec3(0.0), f_diffuse.rgb) + max(vec3(0.0),f_specular.rgb) + max(vec3(0.0), f_emission.rgb)) * (1.0 - f_fog.a) + f_fog.rgb * f_fog.a;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import org.openrndr.draw.shadeStyle
|
|||||||
interface Material {
|
interface Material {
|
||||||
var doubleSided: Boolean
|
var doubleSided: Boolean
|
||||||
var transparent: Boolean
|
var transparent: Boolean
|
||||||
|
val fragmentID: Int
|
||||||
fun generateShadeStyle(context: MaterialContext, primitiveContext: PrimitiveContext): ShadeStyle
|
fun generateShadeStyle(context: MaterialContext, primitiveContext: PrimitiveContext): ShadeStyle
|
||||||
fun applyToShadeStyle(context: MaterialContext, shadeStyle: ShadeStyle)
|
fun applyToShadeStyle(context: MaterialContext, shadeStyle: ShadeStyle)
|
||||||
}
|
}
|
||||||
@@ -15,13 +16,19 @@ interface Material {
|
|||||||
class DummyMaterial : Material {
|
class DummyMaterial : Material {
|
||||||
override var doubleSided: Boolean = true
|
override var doubleSided: Boolean = true
|
||||||
override var transparent: Boolean = false
|
override var transparent: Boolean = false
|
||||||
|
override var fragmentID = 0
|
||||||
|
|
||||||
override fun generateShadeStyle(context: MaterialContext, primitiveContext: PrimitiveContext): ShadeStyle {
|
override fun generateShadeStyle(context: MaterialContext, primitiveContext: PrimitiveContext): ShadeStyle {
|
||||||
return shadeStyle {
|
return shadeStyle {
|
||||||
|
fragmentPreamble = """
|
||||||
|
int f_fragmentID = p_fragmentID;
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
fragmentTransform = """
|
fragmentTransform = """
|
||||||
x_fill.rgb = vec3(normalize(v_viewNormal).z);
|
x_fill.rgb = vec3(normalize(v_viewNormal).z);
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
|
parameter("fragmentID", fragmentID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -264,11 +264,18 @@ class Texture(var source: TextureSource,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var fragmentIDCounter = 1
|
||||||
|
|
||||||
class PBRMaterial : Material {
|
class PBRMaterial : Material {
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "PBRMaterial(textures: $textures, color: $color, metalness: $metalness, roughness: $roughness, emissive: $emission))"
|
return "PBRMaterial(textures: $textures, color: $color, metalness: $metalness, roughness: $roughness, emissive: $emission))"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override var fragmentID = fragmentIDCounter.apply {
|
||||||
|
fragmentIDCounter++
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
override var doubleSided: Boolean = false
|
override var doubleSided: Boolean = false
|
||||||
override var transparent: Boolean = false
|
override var transparent: Boolean = false
|
||||||
var environmentMap = false
|
var environmentMap = false
|
||||||
@@ -277,6 +284,7 @@ class PBRMaterial : Material {
|
|||||||
var roughness = 1.0
|
var roughness = 1.0
|
||||||
var emission = ColorRGBa.BLACK
|
var emission = ColorRGBa.BLACK
|
||||||
|
|
||||||
|
var fragmentPreamble: String? = null
|
||||||
var vertexPreamble: String? = null
|
var vertexPreamble: String? = null
|
||||||
var vertexTransform: String? = null
|
var vertexTransform: String? = null
|
||||||
var parameters = mutableMapOf<String, Any>()
|
var parameters = mutableMapOf<String, Any>()
|
||||||
@@ -304,6 +312,7 @@ class PBRMaterial : Material {
|
|||||||
val needLight = needLight(materialContext)
|
val needLight = needLight(materialContext)
|
||||||
val preambleFS = """
|
val preambleFS = """
|
||||||
vec4 m_color = p_color;
|
vec4 m_color = p_color;
|
||||||
|
uint f_fragmentID = uint(p_fragmentID);
|
||||||
float m_f0 = 0.5;
|
float m_f0 = 0.5;
|
||||||
float m_roughness = p_roughness;
|
float m_roughness = p_roughness;
|
||||||
float m_metalness = p_metalness;
|
float m_metalness = p_metalness;
|
||||||
@@ -415,11 +424,12 @@ class PBRMaterial : Material {
|
|||||||
val vs = (this@PBRMaterial.vertexTransform ?: "") + textureVS + skinVS
|
val vs = (this@PBRMaterial.vertexTransform ?: "") + textureVS + skinVS
|
||||||
|
|
||||||
shadeStyle {
|
shadeStyle {
|
||||||
|
fragmentPreamble = this@PBRMaterial.fragmentPreamble ?: ""
|
||||||
vertexPreamble = """
|
vertexPreamble = """
|
||||||
$shaderNoRepetitionVert
|
$shaderNoRepetitionVert
|
||||||
${(this@PBRMaterial.vertexPreamble) ?: ""}
|
${(this@PBRMaterial.vertexPreamble) ?: ""}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
fragmentPreamble = """
|
fragmentPreamble += """
|
||||||
|$shaderLinePlaneIntersect
|
|$shaderLinePlaneIntersect
|
||||||
|$shaderProjectOnPlane
|
|$shaderProjectOnPlane
|
||||||
|$shaderSideOfPlane
|
|$shaderSideOfPlane
|
||||||
@@ -431,10 +441,14 @@ class PBRMaterial : Material {
|
|||||||
this.vertexTransform = vs
|
this.vertexTransform = vs
|
||||||
fragmentTransform = fs
|
fragmentTransform = fs
|
||||||
materialContext.pass.combiners.map {
|
materialContext.pass.combiners.map {
|
||||||
if (rt.colorBuffers.size <= 1) {
|
if (rt is ProgramRenderTarget) {
|
||||||
this.output(it.targetOutput, 0)
|
this.output(it.targetOutput, ShadeStyleOutput(0))
|
||||||
} else
|
} else {
|
||||||
this.output(it.targetOutput, rt.colorBufferIndex(it.targetOutput))
|
val index = rt.colorBufferIndex(it.targetOutput)
|
||||||
|
val type = rt.colorBuffer(index).type
|
||||||
|
val format = rt.colorBuffer(0).format
|
||||||
|
this.output(it.targetOutput, ShadeStyleOutput(index, format, type))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -453,6 +467,7 @@ class PBRMaterial : Material {
|
|||||||
shadeStyle.parameter("color", color)
|
shadeStyle.parameter("color", color)
|
||||||
shadeStyle.parameter("metalness", metalness)
|
shadeStyle.parameter("metalness", metalness)
|
||||||
shadeStyle.parameter("roughness", roughness)
|
shadeStyle.parameter("roughness", roughness)
|
||||||
|
shadeStyle.parameter("fragmentID", fragmentID)
|
||||||
|
|
||||||
parameters.forEach { (k, v) ->
|
parameters.forEach { (k, v) ->
|
||||||
when (v) {
|
when (v) {
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import org.openrndr.draw.DepthFormat
|
|||||||
import org.openrndr.draw.RenderTarget
|
import org.openrndr.draw.RenderTarget
|
||||||
import org.openrndr.draw.renderTarget
|
import org.openrndr.draw.renderTarget
|
||||||
|
|
||||||
class RenderPass(val combiners: List<FacetCombiner>,
|
data class RenderPass(val combiners: List<FacetCombiner>,
|
||||||
val renderOpaque: Boolean = true,
|
val renderOpaque: Boolean = true,
|
||||||
val renderTransparent: Boolean = false,
|
val renderTransparent: Boolean = false,
|
||||||
val depthWrite: Boolean = true
|
val depthWrite: Boolean = true,
|
||||||
|
val multisample: BufferMultisample = BufferMultisample.Disabled)
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
val DefaultPass = RenderPass(listOf(LDRColorFacet()))
|
val DefaultPass = RenderPass(listOf(LDRColorFacet()))
|
||||||
val DefaultOpaquePass = RenderPass(listOf(LDRColorFacet()), renderOpaque = true, renderTransparent = false)
|
val DefaultOpaquePass = RenderPass(listOf(LDRColorFacet()), renderOpaque = true, renderTransparent = false)
|
||||||
@@ -18,7 +18,7 @@ val DefaultTransparentPass = RenderPass(listOf(LDRColorFacet()), renderOpaque =
|
|||||||
val LightPass = RenderPass(emptyList())
|
val LightPass = RenderPass(emptyList())
|
||||||
val VSMLightPass = RenderPass(listOf(MomentsFacet()))
|
val VSMLightPass = RenderPass(listOf(MomentsFacet()))
|
||||||
|
|
||||||
fun RenderPass.createPassTarget(width: Int, height: Int, depthFormat: DepthFormat = DepthFormat.DEPTH24, multisample: BufferMultisample = BufferMultisample.Disabled): RenderTarget {
|
fun RenderPass.createPassTarget(width: Int, height: Int, depthFormat: DepthFormat = DepthFormat.DEPTH24, multisample: BufferMultisample = this.multisample): RenderTarget {
|
||||||
return renderTarget(width, height, multisample = multisample) {
|
return renderTarget(width, height, multisample = multisample) {
|
||||||
for (combiner in combiners) {
|
for (combiner in combiners) {
|
||||||
when (combiner) {
|
when (combiner) {
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ class SceneRenderer {
|
|||||||
if (pass == outputPasses[0]) {
|
if (pass == outputPasses[0]) {
|
||||||
outputPassTarget?.let {
|
outputPassTarget?.let {
|
||||||
drawer.withTarget(it) {
|
drawer.withTarget(it) {
|
||||||
clear(ColorRGBa.PINK)
|
clear(ColorRGBa.TRANSPARENT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,18 +136,8 @@ class SceneRenderer {
|
|||||||
val postContext = PostContext(lightContext, drawer.view.inversed)
|
val postContext = PostContext(lightContext, drawer.view.inversed)
|
||||||
|
|
||||||
for (postStep in postSteps) {
|
for (postStep in postSteps) {
|
||||||
// if (postStep is FilterPostStep) {
|
|
||||||
// if (postStep.filter is Ssao) {
|
|
||||||
// postStep.filter.projection = drawer.projection
|
|
||||||
// }
|
|
||||||
// if (postStep.filter is Sslr) {
|
|
||||||
// val p = Matrix44.scale(drawer.width / 2.0, drawer.height / 2.0, 1.0) * Matrix44.translate(Vector3(1.0, 1.0, 0.0)) * drawer.projection
|
|
||||||
// postStep.filter.projection = p
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
postStep.apply(buffers, postContext)
|
postStep.apply(buffers, postContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drawer.popStyle()
|
drawer.popStyle()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.openrndr.extra.dnk3
|
package org.openrndr.extra.dnk3
|
||||||
|
|
||||||
val shaderNoRepetition = """
|
val shaderNoRepetition = """
|
||||||
|
// -- shaderNoRepetition
|
||||||
float sum( vec3 v ) { return v.x+v.y+v.z; }
|
float sum( vec3 v ) { return v.x+v.y+v.z; }
|
||||||
|
|
||||||
// based on https://www.shadertoy.com/view/Xtl3zf
|
// based on https://www.shadertoy.com/view/Xtl3zf
|
||||||
@@ -35,7 +36,7 @@ vec4 textureNoTile(in sampler2D noiseTex, in sampler2D tex, in vec2 noiseOffset,
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
val shaderNoRepetitionVert = """
|
val shaderNoRepetitionVert = """
|
||||||
// shaderNoRepetitionVert
|
// -- shaderNoRepetitionVert
|
||||||
float sum( vec3 v ) { return v.x+v.y+v.z; }
|
float sum( vec3 v ) { return v.x+v.y+v.z; }
|
||||||
|
|
||||||
// based on https://www.shadertoy.com/view/Xtl3zf
|
// based on https://www.shadertoy.com/view/Xtl3zf
|
||||||
@@ -67,7 +68,7 @@ vec4 textureNoTile(in sampler2D tex, in vec2 noiseOffset, in vec2 x)
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
val shaderProjectOnPlane = """
|
val shaderProjectOnPlane = """
|
||||||
// shaderProjectOnPlane
|
// -- shaderProjectOnPlane
|
||||||
vec3 projectOnPlane(vec3 p, vec3 pc, vec3 pn) {
|
vec3 projectOnPlane(vec3 p, vec3 pc, vec3 pn) {
|
||||||
float distance = dot(pn, p-pc);
|
float distance = dot(pn, p-pc);
|
||||||
return p - distance * pn;
|
return p - distance * pn;
|
||||||
@@ -75,18 +76,21 @@ vec3 projectOnPlane(vec3 p, vec3 pc, vec3 pn) {
|
|||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
val shaderSideOfPlane = """
|
val shaderSideOfPlane = """
|
||||||
|
// -- shaderSideOfPlane
|
||||||
int sideOfPlane(in vec3 p, in vec3 pc, in vec3 pn){
|
int sideOfPlane(in vec3 p, in vec3 pc, in vec3 pn){
|
||||||
if (dot(p-pc,pn) >= 0.0) return 1; else return 0;
|
if (dot(p-pc,pn) >= 0.0) return 1; else return 0;
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
val shaderLinePlaneIntersect = """
|
val shaderLinePlaneIntersect = """
|
||||||
|
// -- shaderLinePlaneIntersect
|
||||||
vec3 linePlaneIntersect(in vec3 lp, in vec3 lv, in vec3 pc, in vec3 pn){
|
vec3 linePlaneIntersect(in vec3 lp, in vec3 lv, in vec3 pc, in vec3 pn){
|
||||||
return lp+lv*(dot(pn,pc-lp)/dot(pn,lv));
|
return lp+lv*(dot(pn,pc-lp)/dot(pn,lv));
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
val shaderVSM = """
|
val shaderVSM = """
|
||||||
|
|// -- shaderVSM
|
||||||
|float linstep(float min, float max, float v)
|
|float linstep(float min, float max, float v)
|
||||||
|{
|
|{
|
||||||
| return clamp((v - min) / (max - min), 0, 1);
|
| return clamp((v - min) / (max - min), 0, 1);
|
||||||
@@ -112,6 +116,7 @@ V - eye - world vertex position
|
|||||||
L - world light pos - world vertex position
|
L - world light pos - world vertex position
|
||||||
*/
|
*/
|
||||||
val shaderGGX = """
|
val shaderGGX = """
|
||||||
|
// -- shaderGGX
|
||||||
#define bias 0.125
|
#define bias 0.125
|
||||||
#define HASHSCALE 443.8975
|
#define HASHSCALE 443.8975
|
||||||
vec2 hash22(vec2 p) {
|
vec2 hash22(vec2 p) {
|
||||||
|
|||||||
8
orx-dnk3/src/main/kotlin/post/SegmentContours.kt
Normal file
8
orx-dnk3/src/main/kotlin/post/SegmentContours.kt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package org.openrndr.extra.dnk3.post
|
||||||
|
|
||||||
|
import org.openrndr.draw.Filter
|
||||||
|
import org.openrndr.draw.filterShaderFromUrl
|
||||||
|
import org.openrndr.resourceUrl
|
||||||
|
|
||||||
|
class SegmentContoursMSAA8 : Filter(filterShaderFromUrl(resourceUrl("/shaders/segment-contours-msaa-8.frag")))
|
||||||
|
class SegmentContours : Filter(filterShaderFromUrl(resourceUrl("/shaders/segment-contours.frag")))
|
||||||
34
orx-dnk3/src/main/kotlin/renderers/SegmentContourRenderer.kt
Normal file
34
orx-dnk3/src/main/kotlin/renderers/SegmentContourRenderer.kt
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package org.openrndr.extra.dnk3.renderers
|
||||||
|
|
||||||
|
import org.openrndr.draw.BufferMultisample
|
||||||
|
import org.openrndr.draw.ColorFormat
|
||||||
|
import org.openrndr.draw.ColorType
|
||||||
|
import org.openrndr.extra.dnk3.*
|
||||||
|
import org.openrndr.extra.dnk3.post.SegmentContours
|
||||||
|
import org.openrndr.extra.dnk3.post.SegmentContoursMSAA8
|
||||||
|
|
||||||
|
fun segmentContourRenderer(multisample: BufferMultisample = BufferMultisample.Disabled): SceneRenderer {
|
||||||
|
val sr = SceneRenderer()
|
||||||
|
sr.outputPasses.clear()
|
||||||
|
sr.outputPasses.add(
|
||||||
|
RenderPass(
|
||||||
|
listOf(FragmentIDFacet()),
|
||||||
|
multisample = multisample
|
||||||
|
)
|
||||||
|
)
|
||||||
|
sr.postSteps.add(
|
||||||
|
FilterPostStep(1.0,
|
||||||
|
when (multisample) {
|
||||||
|
BufferMultisample.Disabled -> SegmentContours()
|
||||||
|
BufferMultisample.SampleCount(8) -> SegmentContoursMSAA8()
|
||||||
|
else -> error("unsupported multisampling mode $multisample")
|
||||||
|
},
|
||||||
|
listOf("fragmentID"),
|
||||||
|
"segments",
|
||||||
|
ColorFormat.RGB,
|
||||||
|
ColorType.UINT8
|
||||||
|
)
|
||||||
|
)
|
||||||
|
sr.drawFinalBuffer = true
|
||||||
|
return sr
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#version 330
|
||||||
|
|
||||||
|
uniform usampler2DMS tex0;
|
||||||
|
in vec2 v_texCoord0;
|
||||||
|
out vec4 o_output;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
ivec2 ts = textureSize(tex0);
|
||||||
|
ivec2 pixel = ivec2(v_texCoord0 * ts);
|
||||||
|
|
||||||
|
ivec2 c = pixel;
|
||||||
|
ivec2 n = c + ivec2(0, -1);
|
||||||
|
ivec2 s = c + ivec2(0, 1);
|
||||||
|
ivec2 w = c + ivec2(-1, 0);
|
||||||
|
ivec2 e = c + ivec2(1, 0);
|
||||||
|
|
||||||
|
|
||||||
|
float sf = 0.0;
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
float f = 1.0;
|
||||||
|
uint sc = texelFetch(tex0, c, i).r;
|
||||||
|
uint sn = texelFetch(tex0, n, i).r;
|
||||||
|
uint ss = texelFetch(tex0, s, i).r;
|
||||||
|
uint se = texelFetch(tex0, e, i).r;
|
||||||
|
uint sw = texelFetch(tex0, w, i).r;
|
||||||
|
|
||||||
|
if (sc == se) f -= 0.25;
|
||||||
|
if (sc == sw) f -= 0.25;
|
||||||
|
if (sc == sn) f -= 0.25;
|
||||||
|
if (sc == ss) f -= 0.25;
|
||||||
|
sf+= f;
|
||||||
|
}
|
||||||
|
o_output = vec4(vec3(sf/4.0), 1.0);
|
||||||
|
}
|
||||||
33
orx-dnk3/src/main/resources/shaders/segment-contours.frag
Normal file
33
orx-dnk3/src/main/resources/shaders/segment-contours.frag
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#version 330
|
||||||
|
|
||||||
|
uniform usampler2D tex0;
|
||||||
|
in vec2 v_texCoord0;
|
||||||
|
out vec4 o_output;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
ivec2 ts = textureSize(tex0, 0);
|
||||||
|
ivec2 pixel = ivec2(v_texCoord0 * ts);
|
||||||
|
|
||||||
|
ivec2 c = pixel;
|
||||||
|
ivec2 n = c + ivec2(0, -1);
|
||||||
|
ivec2 s = c + ivec2(0, 1);
|
||||||
|
ivec2 w = c + ivec2(-1, 0);
|
||||||
|
ivec2 e = c + ivec2(1, 0);
|
||||||
|
|
||||||
|
float sf = 0.0;
|
||||||
|
for (int i = 0; i < 1; ++i) {
|
||||||
|
float f = 1.0;
|
||||||
|
uint sc = texelFetch(tex0, c, i).r;
|
||||||
|
uint sn = texelFetch(tex0, n, i).r;
|
||||||
|
uint ss = texelFetch(tex0, s, i).r;
|
||||||
|
uint se = texelFetch(tex0, e, i).r;
|
||||||
|
uint sw = texelFetch(tex0, w, i).r;
|
||||||
|
|
||||||
|
if (sc == se) f -= 0.25;
|
||||||
|
if (sc == sw) f -= 0.25;
|
||||||
|
if (sc == sn) f -= 0.25;
|
||||||
|
if (sc == ss) f -= 0.25;
|
||||||
|
sf+= f;
|
||||||
|
}
|
||||||
|
o_output = vec4(vec3(sf/0.5), 1.0);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user