Convert orx-shader-phrases and orx-noise to MPP
This commit is contained in:
257
build.gradle
257
build.gradle
@@ -2,16 +2,37 @@ import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
|
|||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.9.17"
|
classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.9.17"
|
||||||
classpath "com.netflix.nebula:nebula-release-plugin:15.1.0"
|
classpath "com.netflix.nebula:nebula-release-plugin:15.3.1"
|
||||||
classpath "com.github.ben-manes:gradle-versions-plugin:0.28.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
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
|
def openrndrUseSnapshot = true
|
||||||
@@ -22,7 +43,9 @@ ext.isReleaseVersion = !version.endsWith("SNAPSHOT")
|
|||||||
|
|
||||||
project.ext {
|
project.ext {
|
||||||
openrndrVersion = openrndrUseSnapshot? "0.5.1-SNAPSHOT" : "0.4.0"
|
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"
|
spekVersion = "2.0.15"
|
||||||
libfreenectVersion = "0.5.7-1.5.5"
|
libfreenectVersion = "0.5.7-1.5.5"
|
||||||
librealsense2Version = "2.40.0-1.5.5"
|
librealsense2Version = "2.40.0-1.5.5"
|
||||||
@@ -32,6 +55,19 @@ project.ext {
|
|||||||
mklDnnVersion = "0.21.5-1.5.5"
|
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()) {
|
switch (org.gradle.internal.os.OperatingSystem.current()) {
|
||||||
case org.gradle.internal.os.OperatingSystem.WINDOWS:
|
case org.gradle.internal.os.OperatingSystem.WINDOWS:
|
||||||
project.ext.openrndrOS = "windows"
|
project.ext.openrndrOS = "windows"
|
||||||
@@ -52,61 +88,61 @@ dokka {
|
|||||||
sourceDirs = files(subprojects.collect { p -> new File(p.projectDir, "/src/main/kotlin") })
|
sourceDirs = files(subprojects.collect { p -> new File(p.projectDir, "/src/main/kotlin") })
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
//allprojects {
|
||||||
apply plugin: 'idea'
|
// apply plugin: 'idea'
|
||||||
apply plugin: 'java'
|
// apply plugin: 'java'
|
||||||
apply plugin: 'kotlin'
|
// apply plugin: 'kotlin'
|
||||||
apply plugin: 'nebula.release'
|
// apply plugin: 'nebula.release'
|
||||||
|
//
|
||||||
apply plugin: "com.github.ben-manes.versions"
|
// apply plugin: "com.github.ben-manes.versions"
|
||||||
|
//
|
||||||
group 'org.openrndr.extra'
|
// group 'org.openrndr.extra'
|
||||||
|
//
|
||||||
repositories {
|
// repositories {
|
||||||
if (openrndrUseSnapshot) {
|
// if (openrndrUseSnapshot) {
|
||||||
mavenLocal()
|
// mavenLocal()
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
mavenCentral()
|
// mavenCentral()
|
||||||
jcenter()
|
// jcenter()
|
||||||
maven {
|
// maven {
|
||||||
url "https://dl.bintray.com/spekframework/spek"
|
// url "https://dl.bintray.com/spekframework/spek"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
dependencies {
|
// dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
|
// implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
|
||||||
implementation 'io.github.microutils:kotlin-logging-jvm:2.0.6'
|
// implementation 'io.github.microutils:kotlin-logging-jvm:2.0.6'
|
||||||
implementation "org.openrndr:openrndr-application:$openrndrVersion"
|
// implementation "org.openrndr:openrndr-application:$openrndrVersion"
|
||||||
implementation "org.openrndr:openrndr-shape:$openrndrVersion"
|
// implementation "org.openrndr:openrndr-shape:$openrndrVersion"
|
||||||
implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.4.3'
|
// implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.4.3'
|
||||||
testImplementation "org.spekframework.spek2:spek-dsl-jvm:$spekVersion"
|
// testImplementation "org.spekframework.spek2:spek-dsl-jvm:$spekVersion"
|
||||||
testImplementation "org.amshove.kluent:kluent:1.65"
|
// testImplementation "org.amshove.kluent:kluent:1.65"
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion"
|
// testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion"
|
||||||
testRuntimeOnly "org.spekframework.spek2:spek-runner-junit5:$spekVersion"
|
// testRuntimeOnly "org.spekframework.spek2:spek-runner-junit5:$spekVersion"
|
||||||
testRuntimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
// testRuntimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
||||||
runtimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
// runtimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
java {
|
// java {
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
// sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
// targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
}
|
// }
|
||||||
javadoc {
|
// javadoc {
|
||||||
options.addBooleanOption 'Xdoclint:none', true
|
// options.addBooleanOption 'Xdoclint:none', true
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
test {
|
// test {
|
||||||
useJUnitPlatform {
|
// useJUnitPlatform {
|
||||||
includeEngines 'spek2'
|
// includeEngines 'spek2'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
// tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
||||||
kotlinOptions {
|
// kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
// jvmTarget = "1.8"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
task buildMainReadme {
|
task buildMainReadme {
|
||||||
doFirst {
|
doFirst {
|
||||||
@@ -250,76 +286,63 @@ task collectScreenshots {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configure(allprojects.findAll { it.name != "openrndr-demos" }) {
|
configure(allprojects.findAll { !multiplatformModules.contains(it.name) }) {
|
||||||
apply plugin: 'nebula.release'
|
apply plugin: 'idea'
|
||||||
|
apply plugin: 'java'
|
||||||
|
apply plugin: 'kotlin'
|
||||||
apply plugin: 'maven-publish'
|
apply plugin: 'maven-publish'
|
||||||
apply plugin: 'signing'
|
|
||||||
|
|
||||||
java {
|
|
||||||
withJavadocJar()
|
|
||||||
withSourcesJar()
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
mavenJava(MavenPublication) {
|
maven(MavenPublication) {
|
||||||
from components.java
|
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 {
|
tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile).all {
|
||||||
kotlinOptions.freeCompilerArgs += ["-Xuse-experimental=kotlinx.coroutines.InternalCoroutinesApi"]
|
kotlinOptions.freeCompilerArgs += ["-Xuse-experimental=kotlinx.coroutines.InternalCoroutinesApi"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
configure(allprojects.findAll { it.name != "openrndr-demos" }) {
|
||||||
|
apply plugin: 'maven-publish'
|
||||||
|
apply plugin: 'nebula.release'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ sourceSets {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
api project(":orx-osc")
|
api project(":orx-jvm:orx-osc")
|
||||||
|
|
||||||
implementation "com.google.code.gson:gson:$gsonVersion"
|
implementation "com.google.code.gson:gson:$gsonVersion"
|
||||||
demoImplementation("org.openrndr:openrndr-application:$openrndrVersion")
|
demoImplementation("org.openrndr:openrndr-application:$openrndrVersion")
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ dependencies {
|
|||||||
implementation "cc.rabbitcontrol:rcp:0.3.26"
|
implementation "cc.rabbitcontrol:rcp:0.3.26"
|
||||||
implementation "com.google.zxing:core:3.4.0"
|
implementation "com.google.zxing:core:3.4.0"
|
||||||
implementation "com.google.zxing:javase: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")
|
demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion")
|
||||||
demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion")
|
demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion")
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ dependencies {
|
|||||||
demoImplementation(project(":orx-camera"))
|
demoImplementation(project(":orx-camera"))
|
||||||
demoImplementation("org.openrndr:openrndr-application:$openrndrVersion")
|
demoImplementation("org.openrndr:openrndr-application:$openrndrVersion")
|
||||||
demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion")
|
demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion")
|
||||||
|
|
||||||
demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion")
|
demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion")
|
||||||
demoRuntimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion")
|
demoRuntimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion")
|
||||||
demoImplementation(sourceSets.getByName("main").output)
|
demoImplementation(sourceSets.getByName("main").output)
|
||||||
95
orx-noise/build.gradle.kts
Normal file
95
orx-noise/build.gradle.kts
Normal 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"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,
|
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 {
|
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 amp = 1.0
|
||||||
|
|
||||||
var x = x
|
var x = x
|
||||||
@@ -128,7 +128,7 @@ inline fun billow(seed: Int, x: Double, y: Double, z: Double, w: Double, crossin
|
|||||||
z *= lacunarity
|
z *= lacunarity
|
||||||
w *= lacunarity
|
w *= lacunarity
|
||||||
amp *= gain
|
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
|
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,
|
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 {
|
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 amp = 1.0
|
||||||
|
|
||||||
var x = x
|
var x = x
|
||||||
@@ -150,7 +150,7 @@ inline fun billow(seed: Int, x: Double, y: Double, z: Double, crossinline noise:
|
|||||||
y *= lacunarity
|
y *= lacunarity
|
||||||
z *= lacunarity
|
z *= lacunarity
|
||||||
amp *= gain
|
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
|
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,
|
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 {
|
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 amp = 1.0
|
||||||
|
|
||||||
var x = x
|
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,
|
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 {
|
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 amp = 1.0
|
||||||
|
|
||||||
var x = x
|
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,
|
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 {
|
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 amp = 1.0
|
||||||
|
|
||||||
var x = x
|
var x = x
|
||||||
@@ -274,7 +274,7 @@ inline fun rigid(seed: Int, x: Double, y: Double, crossinline noise: (Int, Doubl
|
|||||||
x *= lacunarity
|
x *= lacunarity
|
||||||
y *= lacunarity
|
y *= lacunarity
|
||||||
amp *= gain
|
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
|
return sum
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,9 @@ package org.openrndr.extra.noise
|
|||||||
import org.openrndr.math.Vector2
|
import org.openrndr.math.Vector2
|
||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
import org.openrndr.math.Vector4
|
import org.openrndr.math.Vector4
|
||||||
|
import kotlin.math.ln
|
||||||
|
import kotlin.math.log
|
||||||
|
import kotlin.math.sqrt
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
fun gaussian(mean: Double = 0.0, deviation: Double = 1.0, random: Random = Random.Default): Double {
|
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
|
v2 = 2 * random.nextDouble() - 1
|
||||||
s = v1 * v1 + v2 * v2
|
s = v1 * v1 + v2 * v2
|
||||||
} while (s >= 1 || s == 0.0)
|
} 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
|
return v1 * multiplier * deviation + mean
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package org.openrndr.extra.noise
|
package org.openrndr.extra.noise
|
||||||
|
|
||||||
|
|
||||||
fun Double.fastFloor(): Int {
|
fun Double.fastFloor(): Int {
|
||||||
return if (this >= 0) this.toInt() else this.toInt() - 1
|
return if (this >= 0) this.toInt() else this.toInt() - 1
|
||||||
}
|
}
|
||||||
271
orx-noise/src/commonMain/kotlin/filters/NoiseFilters.kt
Normal file
271
orx-noise/src/commonMain/kotlin/filters/NoiseFilters.kt
Normal 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
|
||||||
|
// }
|
||||||
|
//}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
@file:ShaderPhrases(exports = ["hash22","hash21","valueNoise21"])
|
//@file:ShaderPhrases(exports = ["hash22","hash21","valueNoise21"])
|
||||||
package org.openrndr.extra.noise.phrases
|
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) {
|
val phraseHash22 = """vec2 hash22(vec2 p) {
|
||||||
float n = sin(dot(p, vec2(41, 289)));
|
float n = sin(dot(p, vec2(41, 289)));
|
||||||
return fract(vec2(262144, 32768)*n);
|
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)))); }"
|
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 = fract(p3 * MOD3);
|
||||||
p3 += dot(p3, p3.yxz+19.19);
|
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));
|
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 = """
|
val phraseValueNoise21 = """
|
||||||
|
|
||||||
float noise(vec2 x) {
|
float noise(vec2 x) {
|
||||||
vec2 i = floor(x);
|
vec2 i = floor(x);
|
||||||
vec2 f = fract(x);
|
vec2 f = fract(x);
|
||||||
@@ -33,5 +32,5 @@ float noise(vec2 x) {
|
|||||||
|
|
||||||
vec2 u = f * f * (3.0 - 2.0 * f);
|
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;
|
return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
7
orx-noise/src/commonMain/kotlin/phrases/Simplex.kt
Normal file
7
orx-noise/src/commonMain/kotlin/phrases/Simplex.kt
Normal 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")
|
||||||
@@ -7,6 +7,7 @@ import org.openrndr.extra.noise.simplex
|
|||||||
import org.openrndr.math.Vector2
|
import org.openrndr.math.Vector2
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
|
|
||||||
suspend fun main() {
|
suspend fun main() {
|
||||||
application {
|
application {
|
||||||
program {
|
program {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import org.openrndr.application
|
import org.openrndr.application
|
||||||
import org.openrndr.color.ColorRGBa
|
import org.openrndr.color.ColorRGBa
|
||||||
import org.openrndr.extensions.SingleScreenshot
|
import org.openrndr.extensions.SingleScreenshot
|
||||||
import org.openrndr.extra.noise.poissonDiskSampling
|
import org.openrndr.extra.noise.poissonDiskSampling
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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")
|
|
||||||
99
orx-shader-phrases/build.gradle.kts
Normal file
99
orx-shader-phrases/build.gradle.kts
Normal 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"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
127
orx-shader-phrases/src/commonMain/kotlin/ShaderPreprocessor.kt
Normal file
127
orx-shader-phrases/src/commonMain/kotlin/ShaderPreprocessor.kt
Normal 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)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package org.openrndr.extra.shaderphrases.phrases
|
||||||
|
|
||||||
|
val phraseTbnMatrix = """"""
|
||||||
15
orx-shader-phrases/src/jsMain/kotlin/ShaderPhraseBook.kt
Normal file
15
orx-shader-phrases/src/jsMain/kotlin/ShaderPhraseBook.kt
Normal 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")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,4 +21,4 @@ class PhraseResource<R>(private val resourceUrl: String) : ReadOnlyProperty<R, S
|
|||||||
*/
|
*/
|
||||||
fun phraseResource(resource: String) : PhraseResource<Any?> {
|
fun phraseResource(resource: String) : PhraseResource<Any?> {
|
||||||
return PhraseResource(resourceUrl(resource))
|
return PhraseResource(resourceUrl(resource))
|
||||||
}
|
}
|
||||||
26
orx-shader-phrases/src/jvmMain/kotlin/ShaderPhraseBook.kt
Normal file
26
orx-shader-phrases/src/jvmMain/kotlin/ShaderPhraseBook.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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())
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
@@ -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.*"))
|
|
||||||
}
|
|
||||||
@@ -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()
|
|
||||||
@@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
rootProject.name = 'orx'
|
rootProject.name = 'orx'
|
||||||
|
|
||||||
include 'openrndr-demos',
|
include 'openrndr-demos',
|
||||||
'orx-boofcv',
|
'orx-jvm:orx-boofcv',
|
||||||
'orx-camera',
|
'orx-camera',
|
||||||
'orx-chataigne',
|
'orx-jvm:orx-chataigne',
|
||||||
'orx-color',
|
'orx-color',
|
||||||
'orx-compositor',
|
'orx-compositor',
|
||||||
'orx-dnk3',
|
'orx-dnk3',
|
||||||
|
|||||||
Reference in New Issue
Block a user