Convert orx-shader-phrases and orx-noise to MPP

This commit is contained in:
Edwin Jakobs
2021-06-24 13:31:27 +02:00
parent 6a45db4491
commit 1cf5c825d6
69 changed files with 813 additions and 741 deletions

View File

@@ -2,16 +2,37 @@ import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.9.17"
classpath "com.netflix.nebula:nebula-release-plugin:15.1.0"
classpath "com.github.ben-manes:gradle-versions-plugin:0.28.0"
classpath "com.netflix.nebula:nebula-release-plugin:15.3.1"
}
}
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.5.0'
// remember to update all the versions here when upgrading kotlin version
id 'org.jetbrains.kotlin.jvm' version '1.5.10' apply false
id 'org.jetbrains.kotlin.multiplatform' version '1.5.10' apply false
id 'org.jetbrains.kotlin.plugin.serialization' version '1.5.10' apply false
}
def multiplatformModules = [
"orx-noise",
"orx-shader-phrases"
]
project.ext {
kotlinApiVersion = '1.4'
kotlinLanguageVersion = '1.4'
kotlinVersion = '1.5.10'
kotlinLoggingVersion = '2.0.8'
kotlinxSerializationVersion = '1.1.0'
spekVersion = '2.0.15'
kluentVersion = '1.65'
jsoupVersion = '1.13.1'
kotestVersion = '4.4.3'
junitJupiterVersion = '5.7.1'
}
def openrndrUseSnapshot = true
@@ -22,7 +43,9 @@ ext.isReleaseVersion = !version.endsWith("SNAPSHOT")
project.ext {
openrndrVersion = openrndrUseSnapshot? "0.5.1-SNAPSHOT" : "0.4.0"
kotlinVersion = "1.5.0"
jvmTarget = "1.8"
kotlinVersion = "1.5.10"
kotlinApiVersion = "1.4"
spekVersion = "2.0.15"
libfreenectVersion = "0.5.7-1.5.5"
librealsense2Version = "2.40.0-1.5.5"
@@ -32,6 +55,19 @@ project.ext {
mklDnnVersion = "0.21.5-1.5.5"
}
allprojects {
group 'org.openrndr'
repositories {
mavenCentral()
if (openrndrUseSnapshot) {
mavenLocal()
}
maven {
url = "https://maven.openrndr.org"
}
}
}
switch (org.gradle.internal.os.OperatingSystem.current()) {
case org.gradle.internal.os.OperatingSystem.WINDOWS:
project.ext.openrndrOS = "windows"
@@ -52,61 +88,61 @@ dokka {
sourceDirs = files(subprojects.collect { p -> new File(p.projectDir, "/src/main/kotlin") })
}
allprojects {
apply plugin: 'idea'
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'nebula.release'
apply plugin: "com.github.ben-manes.versions"
group 'org.openrndr.extra'
repositories {
if (openrndrUseSnapshot) {
mavenLocal()
}
mavenCentral()
jcenter()
maven {
url "https://dl.bintray.com/spekframework/spek"
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
implementation 'io.github.microutils:kotlin-logging-jvm:2.0.6'
implementation "org.openrndr:openrndr-application:$openrndrVersion"
implementation "org.openrndr:openrndr-shape:$openrndrVersion"
implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.4.3'
testImplementation "org.spekframework.spek2:spek-dsl-jvm:$spekVersion"
testImplementation "org.amshove.kluent:kluent:1.65"
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion"
testRuntimeOnly "org.spekframework.spek2:spek-runner-junit5:$spekVersion"
testRuntimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
runtimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
javadoc {
options.addBooleanOption 'Xdoclint:none', true
}
test {
useJUnitPlatform {
includeEngines 'spek2'
}
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
jvmTarget = "1.8"
}
}
}
//allprojects {
// apply plugin: 'idea'
// apply plugin: 'java'
// apply plugin: 'kotlin'
// apply plugin: 'nebula.release'
//
// apply plugin: "com.github.ben-manes.versions"
//
// group 'org.openrndr.extra'
//
// repositories {
// if (openrndrUseSnapshot) {
// mavenLocal()
// }
//
// mavenCentral()
// jcenter()
// maven {
// url "https://dl.bintray.com/spekframework/spek"
// }
// }
//
// dependencies {
// implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
// implementation 'io.github.microutils:kotlin-logging-jvm:2.0.6'
// implementation "org.openrndr:openrndr-application:$openrndrVersion"
// implementation "org.openrndr:openrndr-shape:$openrndrVersion"
// implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.4.3'
// testImplementation "org.spekframework.spek2:spek-dsl-jvm:$spekVersion"
// testImplementation "org.amshove.kluent:kluent:1.65"
// testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion"
// testRuntimeOnly "org.spekframework.spek2:spek-runner-junit5:$spekVersion"
// testRuntimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
// runtimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
// }
//
// java {
// sourceCompatibility = JavaVersion.VERSION_1_8
// targetCompatibility = JavaVersion.VERSION_1_8
// }
// javadoc {
// options.addBooleanOption 'Xdoclint:none', true
// }
//
// test {
// useJUnitPlatform {
// includeEngines 'spek2'
// }
// }
// tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
// kotlinOptions {
// jvmTarget = "1.8"
// }
// }
//}
task buildMainReadme {
doFirst {
@@ -250,76 +286,63 @@ task collectScreenshots {
}
}
configure(allprojects.findAll { it.name != "openrndr-demos" }) {
apply plugin: 'nebula.release'
configure(allprojects.findAll { !multiplatformModules.contains(it.name) }) {
apply plugin: 'idea'
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'maven-publish'
apply plugin: 'signing'
java {
withJavadocJar()
withSourcesJar()
}
publishing {
publications {
mavenJava(MavenPublication) {
maven(MavenPublication) {
from components.java
groupId = "org.openrndr.extra"
artifactId = "$project.name"
description = "$project.name"
pom {
name = "$project.name"
description = "$project.name"
url = 'http://openrndr.org'
developers {
developer {
id = 'edwinjakobs'
name = 'Edwin Jakobs'
email = 'edwin@openrndr.org'
}
}
license {
licenses {
license {
name = 'BSD-2-Clause'
url = 'https://github.com/openrndr/openrndr/blob/master/LICENSE'
distribution = 'repo'
}
}
}
scm {
connection = "scm:git:git@github.com:openrndr/openrndr.git"
developerConnection = "scm:git:ssh://github.com/openrndr/openrndr.git"
url = "https://github.com/openrndr/openrndr"
}
}
}
}
repositories {
maven {
credentials {
username findProperty("ossrhUsername") ?: System.getenv("OSSRH_USERNAME")
password findProperty("ossrhPassword") ?: System.getenv("OSSRH_PASSWORD")
}
if (!isReleaseVersion) {
url "https://s01.oss.sonatype.org/content/repositories/snapshots"
} else {
url "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2"
}
}
}
}
signing {
required { isReleaseVersion && gradle.taskGraph.hasTask("publish") }
sign publishing.publications.mavenJava
}
}
configure(subprojects) {
dependencies {
// Note: kotlin-logging and kotlinx-coroutines-core are loaded
// too early and their versions cannot be parametrized
implementation 'io.github.microutils:kotlin-logging:2.0.6'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
implementation "org.openrndr:openrndr-application:$openrndrVersion"
implementation "org.openrndr:openrndr-math:$openrndrVersion"
testImplementation "org.spekframework.spek2:spek-dsl-jvm:$spekVersion"
testImplementation "org.amshove.kluent:kluent:$kluentVersion"
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion"
testRuntimeOnly "org.spekframework.spek2:spek-runner-junit5:$spekVersion"
testRuntimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
}
test {
useJUnitPlatform {
includeEngines 'spek2'
}
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
javadoc {
options.addBooleanOption 'Xdoclint:none', true
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile).all {
kotlinOptions.freeCompilerArgs += ["-Xuse-experimental=kotlinx.coroutines.InternalCoroutinesApi"]
}
}
configure(allprojects.findAll { it.name != "openrndr-demos" }) {
apply plugin: 'maven-publish'
apply plugin: 'nebula.release'
}

View File

@@ -8,7 +8,7 @@ sourceSets {
}
}
dependencies {
api project(":orx-osc")
api project(":orx-jvm:orx-osc")
implementation "com.google.code.gson:gson:$gsonVersion"
demoImplementation("org.openrndr:openrndr-application:$openrndrVersion")

View File

@@ -16,7 +16,7 @@ dependencies {
implementation "cc.rabbitcontrol:rcp:0.3.26"
implementation "com.google.zxing:core:3.4.0"
implementation "com.google.zxing:javase:3.4.0"
implementation "io.ktor:ktor-server-netty:1.3.2"
implementation "io.ktor:ktor-server-netty:1.3.1"
demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion")
demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion")

View File

@@ -15,6 +15,7 @@ dependencies {
demoImplementation(project(":orx-camera"))
demoImplementation("org.openrndr:openrndr-application:$openrndrVersion")
demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion")
demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion")
demoRuntimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion")
demoImplementation(sourceSets.getByName("main").output)

View File

@@ -0,0 +1,95 @@
plugins {
kotlin("multiplatform")
kotlin("plugin.serialization")
}
val kotlinxSerializationVersion: String by rootProject.extra
val kotestVersion: String by rootProject.extra
val junitJupiterVersion: String by rootProject.extra
val jvmTarget: String by rootProject.extra
val kotlinApiVersion: String by rootProject.extra
val openrndrVersion: String by rootProject.extra
val openrndrOS: String by rootProject.extra
val kluentVersion: String by rootProject.extra
val spekVersion: String by rootProject.extra
kotlin {
jvm {
compilations {
val demo by creating {
defaultSourceSet {
kotlin.srcDir("src/demo")
dependencies {
implementation(project(":orx-camera"))
implementation("org.openrndr:openrndr-application:$openrndrVersion")
implementation("org.openrndr:openrndr-extensions:$openrndrVersion")
runtimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion")
runtimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion")
implementation(compilations["main"]!!.output.allOutputs)
}
}
}
}
compilations.all {
kotlinOptions.jvmTarget = jvmTarget
kotlinOptions.apiVersion = kotlinApiVersion
}
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
js(IR) {
browser()
nodejs()
}
sourceSets {
@Suppress("UNUSED_VARIABLE")
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$kotlinxSerializationVersion")
implementation("org.openrndr:openrndr-math:$openrndrVersion")
implementation("org.openrndr:openrndr-shape:$openrndrVersion")
implementation("org.openrndr:openrndr-draw:$openrndrVersion")
}
}
@Suppress("UNUSED_VARIABLE")
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")
implementation("io.kotest:kotest-assertions-core:$kotestVersion")
}
}
@Suppress("UNUSED_VARIABLE")
val jvmMain by getting
@Suppress("UNUSED_VARIABLE")
val jvmTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation(kotlin("test-junit5"))
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")
runtimeOnly("org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion")
runtimeOnly("org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion")
implementation("org.spekframework.spek2:spek-dsl-jvm:$spekVersion")
implementation("org.amshove.kluent:kluent:$kluentVersion")
}
}
@Suppress("UNUSED_VARIABLE")
val jsMain by getting
@Suppress("UNUSED_VARIABLE")
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
}
}

View File

@@ -115,7 +115,7 @@ inline fun billow(seed: Int, position: Vector4, crossinline noise: (Int, Double,
inline fun billow(seed: Int, x: Double, y: Double, z: Double, w: Double, crossinline noise: (Int, Double, Double, Double, Double) -> Double,
octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double {
var sum = Math.abs(noise(seed, x, y, z, w) * 2.0 - 1.0)
var sum = abs(noise(seed, x, y, z, w) * 2.0 - 1.0)
var amp = 1.0
var x = x
@@ -128,7 +128,7 @@ inline fun billow(seed: Int, x: Double, y: Double, z: Double, w: Double, crossin
z *= lacunarity
w *= lacunarity
amp *= gain
sum += Math.abs(noise(seed + i, x, y, z, w) * 2.0 - 1.0) * amp
sum += abs(noise(seed + i, x, y, z, w) * 2.0 - 1.0) * amp
}
return sum
}
@@ -139,7 +139,7 @@ inline fun billow(seed: Int, position: Vector3, crossinline noise: (Int, Double,
inline fun billow(seed: Int, x: Double, y: Double, z: Double, crossinline noise: (Int, Double, Double, Double) -> Double,
octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double {
var sum = Math.abs(noise(seed, x, y, z) * 2.0 - 1.0)
var sum = abs(noise(seed, x, y, z) * 2.0 - 1.0)
var amp = 1.0
var x = x
@@ -150,7 +150,7 @@ inline fun billow(seed: Int, x: Double, y: Double, z: Double, crossinline noise:
y *= lacunarity
z *= lacunarity
amp *= gain
sum += Math.abs(noise(seed + i, x, y, z) * 2.0 - 1.0) * amp
sum += abs(noise(seed + i, x, y, z) * 2.0 - 1.0) * amp
}
return sum
}
@@ -219,7 +219,7 @@ inline fun rigid(seed: Int, position: Vector4, crossinline noise: (Int, Double,
inline fun rigid(seed: Int, x: Double, y: Double, z: Double, w: Double, crossinline noise: (Int, Double, Double, Double, Double) -> Double,
octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double {
var sum = 1.0 - Math.abs(noise(seed, x, y, z, w))
var sum = 1.0 - abs(noise(seed, x, y, z, w))
var amp = 1.0
var x = x
@@ -243,7 +243,7 @@ inline fun rigid(seed: Int, position: Vector3, crossinline noise: (Int, Double,
inline fun rigid(seed: Int, x: Double, y: Double, z: Double, crossinline noise: (Int, Double, Double, Double) -> Double,
octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double {
var sum = 1.0 - Math.abs(noise(seed, x, y, z))
var sum = 1.0 - abs(noise(seed, x, y, z))
var amp = 1.0
var x = x
@@ -265,7 +265,7 @@ inline fun rigid(seed: Int, position: Vector2, crossinline noise: (Int, Double,
inline fun rigid(seed: Int, x: Double, y: Double, crossinline noise: (Int, Double, Double) -> Double,
octaves: Int = 8, lacunarity: Double = 0.5, gain: Double = 0.5): Double {
var sum = 1.0 - Math.abs(noise(seed, x, y))
var sum = 1.0 - abs(noise(seed, x, y))
var amp = 1.0
var x = x
@@ -274,7 +274,7 @@ inline fun rigid(seed: Int, x: Double, y: Double, crossinline noise: (Int, Doubl
x *= lacunarity
y *= lacunarity
amp *= gain
sum -= (1.0 - Math.abs(noise(seed + i, x, y))) * amp
sum -= (1.0 - abs(noise(seed + i, x, y))) * amp
}
return sum
}

View File

@@ -3,6 +3,9 @@ package org.openrndr.extra.noise
import org.openrndr.math.Vector2
import org.openrndr.math.Vector3
import org.openrndr.math.Vector4
import kotlin.math.ln
import kotlin.math.log
import kotlin.math.sqrt
import kotlin.random.Random
fun gaussian(mean: Double = 0.0, deviation: Double = 1.0, random: Random = Random.Default): Double {
@@ -14,7 +17,7 @@ fun gaussian(mean: Double = 0.0, deviation: Double = 1.0, random: Random = Rando
v2 = 2 * random.nextDouble() - 1
s = v1 * v1 + v2 * v2
} while (s >= 1 || s == 0.0)
val multiplier = StrictMath.sqrt(-2 * StrictMath.log(s) / s)
val multiplier = sqrt(-2 * ln(s) / s)
return v1 * multiplier * deviation + mean
}

View File

@@ -1,6 +1,6 @@
package org.openrndr.extra.noise
fun Double.fastFloor(): Int {
return if (this >= 0) this.toInt() else this.toInt() - 1
package org.openrndr.extra.noise
fun Double.fastFloor(): Int {
return if (this >= 0) this.toInt() else this.toInt() - 1
}

View File

@@ -0,0 +1,271 @@
//package org.openrndr.extra.noise.filters
//
//import org.openrndr.color.ColorRGBa
//import org.openrndr.draw.Filter
//import org.openrndr.draw.filterShaderFromUrl
//import org.openrndr.extra.parameters.*
//import org.openrndr.math.Vector2
//import org.openrndr.math.Vector3
//import org.openrndr.math.Vector4
//import org.openrndr.resourceUrl
//
///**
// * Hash noise filter that produces white-noise-like noise.
// */
//class HashNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/hash-noise.frag"))) {
// /**
// * noise gain per channel, default is Vector4(1.0, 1.0, 1.0, 0.0)
// */
// var gain: Vector4 by parameters
//
// /**
// * noise bias per channel, default is Vector4(0.0, 0.0, 0.0, 1.0)
// */
// var bias: Vector4 by parameters
//
// /**
// * is the noise monochrome, default is true
// */
// @BooleanParameter("Monochrome")
// var monochrome: Boolean by parameters
//
// /**
// * noise seed, feed it with time to animate
// */
// @DoubleParameter("Seed", 0.0, 10000.0)
// var seed: Double by parameters
//
// init {
// monochrome = true
// gain = Vector4(1.0, 1.0, 1.0, 0.0)
// bias = Vector4(0.0, 0.0, 0.0, 1.0)
// seed = 0.0
// }
//}
//
///**
// * Speckle noise filter
// */
//class SpeckleNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/speckle-noise.frag"))) {
//
// /**
// * The color of the generated speckles
// */
// @ColorParameter("Color")
// var color: ColorRGBa by parameters
//
// /**
// * Density of the speckles, default is 0.1, min, 0.0, max is 1.0
// */
// @DoubleParameter("Density", 0.0, 1.0)
// var density: Double by parameters
//
//
// /**
// * Noisiness of the generated speckles, default is 0.0, min is 0.0, max is 1.0
// */
// @DoubleParameter("Noise", 0.0, 1.0)
// var noise: Double by parameters
//
// /**
// * should the output colors be multiplied by the alpha channel, default is true
// */
// var premultipliedAlpha: Boolean by parameters
//
// /**
// * noise seed, feed it with time to animate
// */
// @DoubleParameter("Seed", 0.0, 10000.0)
// var seed: Double by parameters
//
// init {
// density = 0.1
// color = ColorRGBa.WHITE
// seed = 0.0
// noise = 0.0
// premultipliedAlpha = true
// }
//}
//
///**
// * Filter that produces cell or Voronoi noise
// */
//class CellNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/cell-noise.frag"))) {
// var seed: Vector2 by parameters
//
// /**
// * base noise scale, default is Vector2(1.0, 1.0)
// */
// var scale: Vector2 by parameters
//
// /**
// * lacunarity is the amount by which scale is modulated per octave, default is Vector2(2.0, 2.0)
// */
// var lacunarity: Vector2 by parameters
//
// /**
// * gain is the base intensity per channel, default is Vector2(1.0, 1.0, 1.0, 1.0)
// */
// var gain: Vector4 by parameters
//
// /**
// * decay is the amount by which gain is modulated per octave, default is Vector4(0.5, 0.5, 0.5, 0.5)
// */
// var decay: Vector4 by parameters
//
// /**
// * the number of octaves of noise to generate, default is 4
// */
// @IntParameter("Octaves", 1, 8)
// var octaves: Int by parameters
//
// /**
// * the value to add to the resulting noise
// */
// var bias: Vector4 by parameters
//
// /**
// * should the output colors be multiplied by the alpha channel, default is true
// */
// var premultipliedAlpha: Boolean by parameters
//
// init {
// seed = Vector2.ZERO
// scale = Vector2.ONE
// lacunarity = Vector2(2.0, 2.0)
// gain = Vector4.ONE
// decay = Vector4.ONE / 2.0
// octaves = 4
// bias = Vector4.ZERO
// premultipliedAlpha = true
// }
//}
//
///**
// * Filter that produces value noise
// */
//class ValueNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/value-noise.frag"))) {
// @DoubleParameter("Seed", 0.0, 10000.0)
// var seed: Vector2 by parameters
//
// /**
// * base noise scale, default is Vector2(1.0, 1.0)
// */
// var scale: Vector2 by parameters
//
// /**
// * lacunarity is the amount by which scale is modulated per octave, default is Vector2(2.0, 2.0)
// */
// var lacunarity: Vector2 by parameters
//
// /**
// * gain is the base intensity per channel, default is Vector2(1.0, 1.0, 1.0, 1.0)
// */
// var gain: Vector4 by parameters
//
// /**
// * decay is the amount by which gain is modulated per octave, default is Vector4(0.5, 0.5, 0.5, 0.5)
// */
// var decay: Vector4 by parameters
//
// /**
// * the number of octaves of noise to generate, default is 4
// */
// @IntParameter("Octaves", 1, 8)
// var octaves: Int by parameters
//
// /**
// * the value to add to the resulting noise
// */
// var bias: Vector4 by parameters
//
// /**
// * should the output colors be multiplied by the alpha channel, default is true
// */
// var premultipliedAlpha: Boolean by parameters
//
// init {
// seed = Vector2.ZERO
// scale = Vector2.ONE
// lacunarity = Vector2(2.0, 2.0)
// gain = Vector4.ONE
// decay = Vector4.ONE / 2.0
// octaves = 4
// bias = Vector4.ZERO
// premultipliedAlpha = true
// }
//}
//
///**
// * Filter that produces 3D Simplex Noise
// */
//@Description("Simplex Noise")
//class SimplexNoise3D : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/simplex-noise-3d.frag"))) {
// var seed: Vector3 by parameters
//
// /**
// * base noise scale, default is Vector3(1.0, 1.0, 1.0)
// */
// var scale: Vector3 by parameters
//
// /**
// * lacunarity is the amount by which scale is modulated per octave, default is Vector3(2.0, 2.0, 2.0)
// */
// var lacunarity: Vector3 by parameters
//
// /**
// * gain is the base intensity per channel, default is Vector2(1.0, 1.0, 1.0, 1.0)
// */
// var gain: Vector4 by parameters
//
// /**
// * decay is the amount by which gain is modulated per octave, default is Vector4(0.5, 0.5, 0.5, 0.5)
// */
// var decay: Vector4 by parameters
//
// /**
// * the number of octaves of noise to generate, default is 4
// */
// @IntParameter("Octaves", 1, 8)
// var octaves: Int by parameters
//
// /**
// * the value to add to the resulting noise
// */
// var bias: Vector4 by parameters
//
// /**
// * should the output colors be multiplied by the alpha channel, default is true
// */
// @BooleanParameter("Premultiplied alpha")
// var premultipliedAlpha: Boolean by parameters
//
// init {
// seed = Vector3.ZERO
// scale = Vector3.ONE
// lacunarity = Vector3(2.0, 2.0, 2.0)
// gain = Vector4.ONE / 2.0
// decay = Vector4.ONE / 2.0
// octaves = 4
// bias = Vector4.ONE / 2.0
// premultipliedAlpha = true
// }
//}
//
//
///**
// * Filter for Worley Noise
// */
//@Description("Worley Noise")
//class WorleyNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/worley-noise.frag"))) {
// @DoubleParameter("Scale", 0.1, 200.0)
// var scale: Double by parameters
//
// @BooleanParameter("Premultiplied alpha")
// var premultipliedAlpha: Boolean by parameters
//
// init {
// premultipliedAlpha = true
// scale = 5.0
// }
//}

View File

@@ -1,12 +1,12 @@
@file:ShaderPhrases(exports = ["hash22","hash21","valueNoise21"])
//@file:ShaderPhrases(exports = ["hash22","hash21","valueNoise21"])
package org.openrndr.extra.noise.phrases
import org.openrndr.extra.shaderphrases.annotations.ShaderPhrases
//import org.openrndr.extra.shaderphrases.annotations.ShaderPhrases
val phraseHash22 = """vec2 hash22(vec2 p) {
float n = sin(dot(p, vec2(41, 289)));
return fract(vec2(262144, 32768)*n);
}
}
"""
val phraseHash21 = "float hash21(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); }"
@@ -17,11 +17,10 @@ vec3 hash33(vec3 p3) {
p3 = fract(p3 * MOD3);
p3 += dot(p3, p3.yxz+19.19);
return -1.0 + 2.0 * fract(vec3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x));
}
}
"""
val phraseValueNoise21 = """
float noise(vec2 x) {
vec2 i = floor(x);
vec2 f = fract(x);
@@ -33,5 +32,5 @@ float noise(vec2 x) {
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
}
}
""".trimIndent()

View File

@@ -0,0 +1,7 @@
//@file:ShaderPhrases([])
package org.openrndr.extra.noise.phrases
//
//import org.openrndr.extra.shaderphrases.annotations.ShaderPhrases
//import org.openrndr.extra.shaderphrases.phraseResource
//
//val phraseSimplex3 by phraseResource("/org/openrndr/extra/noise/phrases/gl3/simplex-3.frag")

View File

@@ -7,6 +7,7 @@ import org.openrndr.extra.noise.simplex
import org.openrndr.math.Vector2
import kotlin.math.absoluteValue
suspend fun main() {
application {
program {

View File

@@ -1,4 +1,4 @@
import org.openrndr.application
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extensions.SingleScreenshot
import org.openrndr.extra.noise.poissonDiskSampling

View File

@@ -1,271 +0,0 @@
package org.openrndr.extra.noise.filters
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.Filter
import org.openrndr.draw.filterShaderFromUrl
import org.openrndr.extra.parameters.*
import org.openrndr.math.Vector2
import org.openrndr.math.Vector3
import org.openrndr.math.Vector4
import org.openrndr.resourceUrl
/**
* Hash noise filter that produces white-noise-like noise.
*/
class HashNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/hash-noise.frag"))) {
/**
* noise gain per channel, default is Vector4(1.0, 1.0, 1.0, 0.0)
*/
var gain: Vector4 by parameters
/**
* noise bias per channel, default is Vector4(0.0, 0.0, 0.0, 1.0)
*/
var bias: Vector4 by parameters
/**
* is the noise monochrome, default is true
*/
@BooleanParameter("Monochrome")
var monochrome: Boolean by parameters
/**
* noise seed, feed it with time to animate
*/
@DoubleParameter("Seed", 0.0, 10000.0)
var seed: Double by parameters
init {
monochrome = true
gain = Vector4(1.0, 1.0, 1.0, 0.0)
bias = Vector4(0.0, 0.0, 0.0, 1.0)
seed = 0.0
}
}
/**
* Speckle noise filter
*/
class SpeckleNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/speckle-noise.frag"))) {
/**
* The color of the generated speckles
*/
@ColorParameter("Color")
var color: ColorRGBa by parameters
/**
* Density of the speckles, default is 0.1, min, 0.0, max is 1.0
*/
@DoubleParameter("Density", 0.0, 1.0)
var density: Double by parameters
/**
* Noisiness of the generated speckles, default is 0.0, min is 0.0, max is 1.0
*/
@DoubleParameter("Noise", 0.0, 1.0)
var noise: Double by parameters
/**
* should the output colors be multiplied by the alpha channel, default is true
*/
var premultipliedAlpha: Boolean by parameters
/**
* noise seed, feed it with time to animate
*/
@DoubleParameter("Seed", 0.0, 10000.0)
var seed: Double by parameters
init {
density = 0.1
color = ColorRGBa.WHITE
seed = 0.0
noise = 0.0
premultipliedAlpha = true
}
}
/**
* Filter that produces cell or Voronoi noise
*/
class CellNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/cell-noise.frag"))) {
var seed: Vector2 by parameters
/**
* base noise scale, default is Vector2(1.0, 1.0)
*/
var scale: Vector2 by parameters
/**
* lacunarity is the amount by which scale is modulated per octave, default is Vector2(2.0, 2.0)
*/
var lacunarity: Vector2 by parameters
/**
* gain is the base intensity per channel, default is Vector2(1.0, 1.0, 1.0, 1.0)
*/
var gain: Vector4 by parameters
/**
* decay is the amount by which gain is modulated per octave, default is Vector4(0.5, 0.5, 0.5, 0.5)
*/
var decay: Vector4 by parameters
/**
* the number of octaves of noise to generate, default is 4
*/
@IntParameter("Octaves", 1, 8)
var octaves: Int by parameters
/**
* the value to add to the resulting noise
*/
var bias: Vector4 by parameters
/**
* should the output colors be multiplied by the alpha channel, default is true
*/
var premultipliedAlpha: Boolean by parameters
init {
seed = Vector2.ZERO
scale = Vector2.ONE
lacunarity = Vector2(2.0, 2.0)
gain = Vector4.ONE
decay = Vector4.ONE / 2.0
octaves = 4
bias = Vector4.ZERO
premultipliedAlpha = true
}
}
/**
* Filter that produces value noise
*/
class ValueNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/value-noise.frag"))) {
@DoubleParameter("Seed", 0.0, 10000.0)
var seed: Vector2 by parameters
/**
* base noise scale, default is Vector2(1.0, 1.0)
*/
var scale: Vector2 by parameters
/**
* lacunarity is the amount by which scale is modulated per octave, default is Vector2(2.0, 2.0)
*/
var lacunarity: Vector2 by parameters
/**
* gain is the base intensity per channel, default is Vector2(1.0, 1.0, 1.0, 1.0)
*/
var gain: Vector4 by parameters
/**
* decay is the amount by which gain is modulated per octave, default is Vector4(0.5, 0.5, 0.5, 0.5)
*/
var decay: Vector4 by parameters
/**
* the number of octaves of noise to generate, default is 4
*/
@IntParameter("Octaves", 1, 8)
var octaves: Int by parameters
/**
* the value to add to the resulting noise
*/
var bias: Vector4 by parameters
/**
* should the output colors be multiplied by the alpha channel, default is true
*/
var premultipliedAlpha: Boolean by parameters
init {
seed = Vector2.ZERO
scale = Vector2.ONE
lacunarity = Vector2(2.0, 2.0)
gain = Vector4.ONE
decay = Vector4.ONE / 2.0
octaves = 4
bias = Vector4.ZERO
premultipliedAlpha = true
}
}
/**
* Filter that produces 3D Simplex Noise
*/
@Description("Simplex Noise")
class SimplexNoise3D : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/simplex-noise-3d.frag"))) {
var seed: Vector3 by parameters
/**
* base noise scale, default is Vector3(1.0, 1.0, 1.0)
*/
var scale: Vector3 by parameters
/**
* lacunarity is the amount by which scale is modulated per octave, default is Vector3(2.0, 2.0, 2.0)
*/
var lacunarity: Vector3 by parameters
/**
* gain is the base intensity per channel, default is Vector2(1.0, 1.0, 1.0, 1.0)
*/
var gain: Vector4 by parameters
/**
* decay is the amount by which gain is modulated per octave, default is Vector4(0.5, 0.5, 0.5, 0.5)
*/
var decay: Vector4 by parameters
/**
* the number of octaves of noise to generate, default is 4
*/
@IntParameter("Octaves", 1, 8)
var octaves: Int by parameters
/**
* the value to add to the resulting noise
*/
var bias: Vector4 by parameters
/**
* should the output colors be multiplied by the alpha channel, default is true
*/
@BooleanParameter("Premultiplied alpha")
var premultipliedAlpha: Boolean by parameters
init {
seed = Vector3.ZERO
scale = Vector3.ONE
lacunarity = Vector3(2.0, 2.0, 2.0)
gain = Vector4.ONE / 2.0
decay = Vector4.ONE / 2.0
octaves = 4
bias = Vector4.ONE / 2.0
premultipliedAlpha = true
}
}
/**
* Filter for Worley Noise
*/
@Description("Worley Noise")
class WorleyNoise : Filter(filterShaderFromUrl(resourceUrl("/org/openrndr/extra/noise/shaders/gl3/worley-noise.frag"))) {
@DoubleParameter("Scale", 0.1, 200.0)
var scale: Double by parameters
@BooleanParameter("Premultiplied alpha")
var premultipliedAlpha: Boolean by parameters
init {
premultipliedAlpha = true
scale = 5.0
}
}

View File

@@ -1,7 +0,0 @@
@file:ShaderPhrases([])
package org.openrndr.extra.noise.phrases
import org.openrndr.extra.shaderphrases.annotations.ShaderPhrases
import org.openrndr.extra.shaderphrases.phraseResource
val phraseSimplex3 by phraseResource("/org/openrndr/extra/noise/phrases/gl3/simplex-3.frag")

View File

@@ -0,0 +1,99 @@
plugins {
kotlin("multiplatform")
kotlin("plugin.serialization")
}
val kotlinxSerializationVersion: String by rootProject.extra
val kotestVersion: String by rootProject.extra
val junitJupiterVersion: String by rootProject.extra
val jvmTarget: String by rootProject.extra
val kotlinApiVersion: String by rootProject.extra
val kotlinVersion: String by rootProject.extra
val kotlinLoggingVersion: String by rootProject.extra
val kluentVersion: String by rootProject.extra
val openrndrVersion: String by rootProject.extra
val openrndrOS: String by rootProject.extra
val spekVersion: String by rootProject.extra
kotlin {
jvm {
compilations {
val demo by creating {
defaultSourceSet {
kotlin.srcDir("src/demo")
dependencies {
implementation(project(":orx-camera"))
implementation("org.openrndr:openrndr-application:$openrndrVersion")
implementation("org.openrndr:openrndr-extensions:$openrndrVersion")
runtimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion")
runtimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion")
implementation(compilations["main"]!!.output.allOutputs)
}
}
}
}
compilations.all {
kotlinOptions.jvmTarget = jvmTarget
kotlinOptions.apiVersion = kotlinApiVersion
}
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
js(IR) {
browser()
nodejs()
}
sourceSets {
@Suppress("UNUSED_VARIABLE")
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$kotlinxSerializationVersion")
implementation("org.openrndr:openrndr-application:$openrndrVersion")
implementation("org.openrndr:openrndr-draw:$openrndrVersion")
implementation("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")
implementation("io.github.microutils:kotlin-logging:$kotlinLoggingVersion")
}
}
@Suppress("UNUSED_VARIABLE")
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")
implementation("io.kotest:kotest-assertions-core:$kotestVersion")
}
}
@Suppress("UNUSED_VARIABLE")
val jvmMain by getting
@Suppress("UNUSED_VARIABLE")
val jvmTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation(kotlin("test-junit5"))
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")
runtimeOnly("org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion")
runtimeOnly("org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion")
implementation("org.spekframework.spek2:spek-dsl-jvm:$spekVersion")
implementation("org.amshove.kluent:kluent:$kluentVersion")
}
}
@Suppress("UNUSED_VARIABLE")
val jsMain by getting
@Suppress("UNUSED_VARIABLE")
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
}
}

View File

@@ -0,0 +1,127 @@
package org.openrndr.extra.shaderphrases
import mu.KotlinLogging
import org.openrndr.draw.Shader
import org.openrndr.utils.url.textFromURL
private val logger = KotlinLogging.logger {}
/**
* A single shader phrase.
*/
class ShaderPhrase(val phrase: String) {
/**
* Register this shader phrase in the [ShaderPhraseRegistry]
* This will likely be called by [ShaderPhraseBook]
*/
fun register(bookId: String? = null) {
val functionRex =
Regex("(float|int|[bi]?vec2|[bi]?vec3|[bi]?vec4|mat3|mat4)[ ]+([a-zA-Z0-9_]+)[ ]*\\(.*\\).*")
val defs = phrase.split("\n").filter {
functionRex.matches(it)
}.take(1).mapNotNull {
val m = functionRex.find(it)
m?.groupValues?.getOrNull(2)
}
val id = defs.firstOrNull() ?: error("no function body found in phrase")
ShaderPhraseRegistry.registerPhrase("${bookId?.let { "$it." } ?: ""}$id", this)
}
}
/**
* A book of shader phrases.
*/
expect open class ShaderPhraseBook(bookId: String) {
//private var registered = false
/**
* Registers all known shader phrases
*/
fun register()
}
/**
* The global, application-wide, shader phrase registry
*/
object ShaderPhraseRegistry {
private val phrases = mutableMapOf<String, ShaderPhrase>()
/**
* Registers a [phrase] with [id]
*/
fun registerPhrase(id: String, phrase: ShaderPhrase) {
phrases[id] = phrase
}
/**
* Finds a phrase for [id], returns null when no phrase found
*/
fun findPhrase(id: String): ShaderPhrase? {
val phrase = phrases[id]
if (phrase == null) {
logger.warn { "no phrase found for id: \"$id\"" }
}
return phrase
}
}
/**
* Preprocess shader source.
* Looks for "#pragma import" statements and injects found phrases.
* @param source GLSL source code encoded as string
* @return GLSL source code with injected shader phrases
*/
fun preprocessShader(source: String, symbols: Set<String> = emptySet()): String {
val newSymbols = mutableSetOf<String>()
newSymbols.addAll(symbols)
val lines = source.split("\n")
val processed = lines.mapIndexed { index, it ->
if (it.startsWith("#pragma import")) {
val tokens = it.split(" ")
val symbol = tokens[2].trim().replace(";", "")
val fullTokens = symbol.split(".")
val fieldName = fullTokens.last().replace(";", "").trim()
val packageClassTokens = fullTokens.dropLast(1)
val packageClass = packageClassTokens.joinToString(".")
if (symbol !in newSymbols) {
newSymbols.add(symbol)
val registryPhrase = ShaderPhraseRegistry.findPhrase(symbol)
registryPhrase?.let { preprocessShader(it.phrase, newSymbols) }
} else {
""
}
} else {
it
}
}
return processed.joinToString("\n")
}
fun String.preprocess() = preprocessShader(this)
/**
* Preprocess shader source from url
* Looks for "#pragma import" statements and injects found phrases.
* @param url url pointing to GLSL shader source
* @return GLSL source code with injected shader phrases
*/
fun preprocessShaderFromUrl(url: String, symbols: Set<String> = emptySet()): String {
return preprocessShader(textFromURL(url), symbols)
}
fun Shader.Companion.preprocessedFromUrls(
vsUrl: String,
tcsUrl: String? = null,
tesUrl: String? = null,
gsUrl: String? = null,
fsUrl: String
): Shader {
val vsCode = textFromURL(vsUrl).preprocess()
val tcsCode = tcsUrl?.let { textFromURL(it) }?.preprocess()
val tesCode = tesUrl?.let { textFromURL(it) }?.preprocess()
val gsCode = gsUrl?.let { textFromURL(it) }?.preprocess()
val fsCode = textFromURL(fsUrl).preprocess()
val name = "$$vsUrl / $gsUrl / $fsUrl"
return Shader.createFromCode(vsCode, tcsCode, tesCode, gsCode, fsCode, name)
}

View File

@@ -0,0 +1,3 @@
package org.openrndr.extra.shaderphrases.phrases
val phraseTbnMatrix = """"""

View File

@@ -0,0 +1,15 @@
package org.openrndr.extra.shaderphrases
/**
* A book of shader phrases.
*/
actual open class ShaderPhraseBook actual constructor(val bookId: String) {
private var registered = false
/**
* Registers all known shader phrases
*/
actual fun register() {
error("not supported")
}
}

View File

@@ -21,4 +21,4 @@ class PhraseResource<R>(private val resourceUrl: String) : ReadOnlyProperty<R, S
*/
fun phraseResource(resource: String) : PhraseResource<Any?> {
return PhraseResource(resourceUrl(resource))
}
}

View File

@@ -0,0 +1,26 @@
package org.openrndr.extra.shaderphrases
import kotlin.reflect.KProperty1
import kotlin.reflect.full.declaredMemberProperties
/**
* A book of shader phrases.
*/
actual open class ShaderPhraseBook actual constructor(val bookId: String) {
private var registered = false
/**
* Registers all known shader phrases
*/
actual fun register() {
if (!registered) {
this::class.declaredMemberProperties.filter {
it.returnType.toString() == "org.openrndr.extra.shaderphrases.ShaderPhrase"
}.map {
@Suppress("UNCHECKED_CAST")
val m = it as? KProperty1<ShaderPhraseBook, ShaderPhrase>
m?.get(this)?.register(bookId)
}
registered = true
}
}
}

View File

@@ -1,183 +0,0 @@
package org.openrndr.extra.shaderphrases
import mu.KotlinLogging
import org.openrndr.draw.Shader
import org.openrndr.draw.codeFromURL
import org.openrndr.extra.shaderphrases.annotations.ShaderPhrases
import kotlin.reflect.KProperty1
import kotlin.reflect.full.declaredMemberProperties
private val logger = KotlinLogging.logger {}
/**
* A single shader phrase.
*/
class ShaderPhrase(val phrase: String) {
/**
* Register this shader phrase in the [ShaderPhraseRegistry]
* This will likely be called by [ShaderPhraseBook]
*/
fun register(bookId: String? = null) {
val functionRex =
Regex("(float|int|[bi]?vec2|[bi]?vec3|[bi]?vec4|mat3|mat4)[ ]+([a-zA-Z0-9_]+)[ ]*\\(.*\\).*")
val defs = phrase.split("\n").filter {
functionRex.matches(it)
}.take(1).mapNotNull {
val m = functionRex.find(it)
m?.groupValues?.getOrNull(2)
}
val id = defs.firstOrNull() ?: error("no function body found in phrase")
ShaderPhraseRegistry.registerPhrase("${bookId?.let { "$it." } ?: ""}$id", this)
}
}
/**
* A book of shader phrases.
*/
open class ShaderPhraseBook(val bookId: String) {
private var registered = false
/**
* Registers all known shader phrases
*/
fun register() {
if (!registered) {
this::class.declaredMemberProperties.filter {
it.returnType.toString() == "org.openrndr.extra.shaderphrases.ShaderPhrase"
}.map {
@Suppress("UNCHECKED_CAST")
val m = it as? KProperty1<ShaderPhraseBook, ShaderPhrase>
m?.get(this)?.register(bookId)
}
registered = true
}
}
}
/**
* The global, application-wide, shader phrase registry
*/
object ShaderPhraseRegistry {
private val phrases = mutableMapOf<String, ShaderPhrase>()
/**
* Registers a [phrase] with [id]
*/
fun registerPhrase(id: String, phrase: ShaderPhrase) {
phrases[id] = phrase
}
/**
* Finds a phrase for [id], returns null when no phrase found
*/
fun findPhrase(id: String): ShaderPhrase? {
val phrase = phrases[id]
if (phrase == null) {
logger.warn { "no phrase found for id: \"$id\"" }
}
return phrase
}
}
/**
* Preprocess shader source.
* Looks for "#pragma import" statements and injects found phrases.
* @param source GLSL source code encoded as string
* @return GLSL source code with injected shader phrases
*/
fun preprocessShader(source: String, symbols: Set<String> = emptySet()): String {
val newSymbols = mutableSetOf<String>()
newSymbols.addAll(symbols)
val lines = source.split("\n")
val processed = lines.mapIndexed { index, it ->
if (it.startsWith("#pragma import")) {
val tokens = it.split(" ")
val symbol = tokens[2].trim().replace(";", "")
val fullTokens = symbol.split(".")
val fieldName = fullTokens.last().replace(";", "").trim()
val packageClassTokens = fullTokens.dropLast(1)
val packageClass = packageClassTokens.joinToString(".")
if (symbol !in newSymbols) {
newSymbols.add(symbol)
val registryPhrase = ShaderPhraseRegistry.findPhrase(symbol)
registryPhrase?.let { preprocessShader(it.phrase, newSymbols) }
?: try {
/* Note that JVM-style reflection is used here because of short-comings in the Kotlin reflection
library (as of 1.3.61), most notably reflection support for file facades is missing. */
val c = Class.forName(packageClass)
if (c.annotations.any { it.annotationClass == ShaderPhrases::class }) {
if (fieldName == "*") {
c.declaredMethods.filter { it.returnType.name == "java.lang.String" }.map {
"/* imported from $packageClass.$it */\n${it.invoke(null)}\n"
}.joinToString("\n") +
c.declaredFields.filter { it.type.name == "java.lang.String" }.map {
"/* imported from $packageClass.$it */\n${it.get(null)}\n"
}.joinToString("\n")
} else {
var result: String?
try {
val methodName = "get${fieldName.take(1).toUpperCase() + fieldName.drop(1)}"
result =
preprocessShader(c.getMethod(methodName).invoke(null) as String, newSymbols)
} catch (e: NoSuchMethodException) {
try {
result =
preprocessShader(
c.getDeclaredField(fieldName).get(null) as String,
newSymbols
)
} catch (e: NoSuchFieldException) {
println(source)
error("field \"$fieldName\" not found in \"#pragma import $packageClass.$fieldName\" on line ${index + 1}")
}
}
result
}
} else {
throw IllegalArgumentException("class $packageClass has no ShaderPhrases annotation")
}
} catch (e: ClassNotFoundException) {
println(source)
error("class \"$packageClass\" not found in \"#pragma import $packageClass\" on line ${index + 1}")
}
} else {
""
}
} else {
it
}
}
return processed.joinToString("\n")
}
fun String.preprocess() = preprocessShader(this)
/**
* Preprocess shader source from url
* Looks for "#pragma import" statements and injects found phrases.
* @param url url pointing to GLSL shader source
* @return GLSL source code with injected shader phrases
*/
fun preprocessShaderFromUrl(url: String, symbols: Set<String> = emptySet()): String {
return preprocessShader(codeFromURL(url), symbols)
}
fun Shader.Companion.preprocessedFromUrls(
vsUrl: String,
tcsUrl: String? = null,
tesUrl: String? = null,
gsUrl: String? = null,
fsUrl: String
): Shader {
val vsCode = codeFromURL(vsUrl).preprocess()
val tcsCode = tcsUrl?.let { codeFromURL(it) }?.preprocess()
val tesCode = tesUrl?.let { codeFromURL(it) }?.preprocess()
val gsCode = gsUrl?.let { codeFromURL(it) }?.preprocess()
val fsCode = codeFromURL(fsUrl).preprocess()
val name = "$$vsUrl / $gsUrl / $fsUrl"
return Shader.createFromCode(vsCode, tcsCode, tesCode, gsCode, fsCode, name)
}

View File

@@ -1,8 +0,0 @@
package org.openrndr.extra.shaderphrases.annotations
enum class ShaderPhraseLanguage {
GLSL_330
}
@Target(AnnotationTarget.FILE)
annotation class ShaderPhrases(val exports: Array<String> = emptyArray())

View File

@@ -1,42 +0,0 @@
@file:JvmName("Depth")
@file:ShaderPhrases([])
package org.openrndr.extra.shaderphrases.phrases
import org.openrndr.extra.shaderphrases.annotations.ShaderPhrases
/**
* phrase for conversion from view to projection depth
* @param viewDepth depth in view space ([0.0 .. -far])
* @param projection projection matrix
* @return depth in projection space ([0.0 .. 1.0]]
*/
const val viewToProjectionDepth = """
float viewToProjectionDepth(float viewDepth, mat4 projection) {
float z = viewDepth * projection[2].z + projection[3].z;
float w = viewDepth * projection[2].w + projection[3].w;
return z / w;
}
"""
/**
* phrase for conversion from projection to view depth
* @param projectionDepth depth in projection space ([0.0 .. 1.0])
* @param projectionInversed inverse of the projection matrix
* @return depth in view space ([0.0 .. -far]]
*/
const val projectionToViewDepth = """
float projectionToViewDepth(float projectionDepth, mat4 projectionInverse) {
float z = (projectionDepth*2.0-1.0) * projectionInverse[2].z + projectionInverse[3].z;
float w = (projectionDepth*2.0-1.0) * projectionInverse[2].w + projectionInverse[3].w;
return z / w;
}
"""
const val projectionToViewCoordinate = """
vec3 projectionToViewCoordinate(vec2 uv, float projectionDepth, mat4 projectionInverse) {
vec4 projectionCoordinate = vec4(uv * 2.0 - 1.0, projectionDepth*2.0-1.0, 1.0);
vec4 viewCoordinate = projectionInverse * projectionCoordinate;
return viewCoordinate.xyz / viewCoordinate.w;
}
"""

View File

@@ -1,21 +0,0 @@
@file:JvmName("Dummy")
@file:ShaderPhrases
package org.openrndr.extra.shaderphrases.phrases
import org.openrndr.extra.shaderphrases.annotations.ShaderPhrases
import org.openrndr.extra.shaderphrases.preprocessShader
const val phraseDummy = """
float dummy() {
return 0.0;
}
"""
fun main() {
val c = Class.forName("org.openrndr.extra.shaderphrases.phrases.Dummy")
if (c.annotations.any { it.annotationClass == ShaderPhrases::class }) {
println(c.getDeclaredField("phraseDummy").get(null))
}
println(preprocessShader("import org.openrndr.extra.shaderphrases.phrases.Dummy.*"))
}

View File

@@ -1,13 +0,0 @@
@file:JvmName("NormalMapping")
@file:ShaderPhrases
package org.openrndr.extra.shaderphrases.phrases
import org.openrndr.extra.shaderphrases.annotations.ShaderPhrases
val phraseTbnMatrix = """
mat3 tbnMatrix(vec4 tangent, vec3 normal) {
vec3 bitangent = cross(normal, tangent.xyz) * tangent.w;
return mat3(tangent.xyz, bitangent, normal);
}
""".trimIndent()

View File

@@ -1,53 +0,0 @@
import org.amshove.kluent.`should contain`
import org.amshove.kluent.`should throw`
import org.amshove.kluent.`with message`
import org.amshove.kluent.invoking
import org.openrndr.extra.shaderphrases.preprocessShader
import org.openrndr.extra.shaderphrases.preprocessShaderFromUrl
import org.openrndr.resourceUrl
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
object TestPreprocessShader : Spek({
describe("An url pointing to a shader resource") {
val url = resourceUrl("/from-url-test.frag")
describe("results in injected dummy phrase when preprocessed") {
val processed = preprocessShaderFromUrl(url)
processed `should contain` "float dummy"
}
}
describe("A shader with import statements") {
val shader = """
|#version 330
|#pragma import org.openrndr.extra.shaderphrases.phrases.Dummy.*""".trimMargin()
describe("injects dummy phrase when preprocessed") {
val processed = preprocessShader(shader)
processed `should contain` "float dummy"
}
}
describe("A shader with non-resolvable class statements") {
val shader = """#version 330
#pragma import invalid.Class.*
"""
describe("throws exception when preprocessed") {
invoking {
preprocessShader(shader)
} `should throw` RuntimeException::class `with message`
("class \"invalid.Class\" not found in \"#pragma import invalid.Class\" on line 2")
}
}
describe("A shader with non-resolvable property statements") {
val shader = """#version 330
#pragma import org.openrndr.extra.shaderphrases.phrases.Dummy.invalid
"""
describe("throws exception when preprocessed") {
invoking {
preprocessShader(shader)
} `should throw` RuntimeException::class `with message`
("field \"invalid\" not found in \"#pragma import org.openrndr.extra.shaderphrases.phrases.Dummy.invalid\" on line 2")
}
}
})

View File

@@ -1,9 +1,9 @@
rootProject.name = 'orx'
include 'openrndr-demos',
'orx-boofcv',
'orx-jvm:orx-boofcv',
'orx-camera',
'orx-chataigne',
'orx-jvm:orx-chataigne',
'orx-color',
'orx-compositor',
'orx-dnk3',