diff --git a/build.gradle b/build.gradle index 72589a0b..0ce25576 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ buildscript { plugins { // plugin dependencies, load without applying them - id 'nebula.kotlin' version '1.3.41' apply false + id 'nebula.kotlin' version '1.3.50' apply false id 'com.jfrog.artifactory' version '4.6.2' apply false id 'nebula.contacts' version '4.1.1' apply false @@ -38,7 +38,7 @@ plugins { project.ext { openrndrVersion = "0.3.35" - kotlinVersion = "1.3.41" + kotlinVersion = "1.3.50" spekVersion = "2.0.6" libfreenectVersion = "0.5.7-1.5.1" } @@ -66,16 +66,14 @@ allprojects { repositories { mavenCentral() + jcenter() maven { url = "https://dl.bintray.com/openrndr/openrndr" } - maven { url "https://dl.bintray.com/spekframework/spek" } - - } dependencies { @@ -83,11 +81,12 @@ allprojects { compile "org.openrndr:openrndr-filter:$openrndrVersion" compile "org.openrndr:openrndr-shape:$openrndrVersion" compile group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.3.0-RC2' - testImplementation "org.spekframework.spek2:spek-dsl-jvm:$spekVersion" + testImplementation "org.amshove.kluent:kluent:1.53" testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" testRuntimeOnly "org.spekframework.spek2:spek-runner-junit5:$spekVersion" testRuntimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion" + runtime "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion" } contacts { diff --git a/orx-noise/build.gradle b/orx-noise/build.gradle new file mode 100644 index 00000000..3cc46fa0 --- /dev/null +++ b/orx-noise/build.gradle @@ -0,0 +1,3 @@ +dependencies { + implementation project(":orx-shader-phrases") +} \ No newline at end of file diff --git a/orx-noise/src/main/kotlin/phrases/NoisePhrases.kt b/orx-noise/src/main/kotlin/phrases/NoisePhrases.kt new file mode 100644 index 00000000..d92129c6 --- /dev/null +++ b/orx-noise/src/main/kotlin/phrases/NoisePhrases.kt @@ -0,0 +1,32 @@ +@file:ShaderPhrases(exports = ["hash22","hash21","valueNoise21"]) +package org.openrndr.extra.noise.phrases + +import org.openrndr.extra.shaderphrases.annotations.ShaderPhrase +import org.openrndr.extra.shaderphrases.annotations.ShaderPhrases + +@ShaderPhrase(exports = ["hash22"]) +val phraseHash22 = """vec2 hash22(vec2 p) { + float n = sin(dot(p, vec2(41, 289))); + return fract(vec2(262144, 32768)*n); +} +""" + +@ShaderPhrase(exports = ["hash21"]) +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)))); }" + +@ShaderPhrase(exports = ["valueNoise21"], imports = ["hash21"]) +val phraseValueNoise21 = """ + +float noise(vec2 x) { + vec2 i = floor(x); + vec2 f = fract(x); + + float a = hash21(i); + float b = hash21(i + vec2(1.0, 0.0)); + float c = hash21(i + vec2(0.0, 1.0)); + float d = hash21(i + vec2(1.0, 1.0)); + + 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() diff --git a/orx-shader-phrases/src/main/kotlin/ShaderPreprocessor.kt b/orx-shader-phrases/src/main/kotlin/ShaderPreprocessor.kt new file mode 100644 index 00000000..ab1380be --- /dev/null +++ b/orx-shader-phrases/src/main/kotlin/ShaderPreprocessor.kt @@ -0,0 +1,33 @@ +package org.openrndr.extra.shaderphrases + +import org.openrndr.extra.shaderphrases.annotations.ShaderPhrases + +fun preprocessShader(shader: String): String { + val lines = shader.split("\n") + val processed = lines.map { + if (it.startsWith("import ")) { + val tokens = it.split(" ") + val full = tokens[1] + val fullTokens = full.split(".") + val fieldName = fullTokens.last().replace(";","") + val packageClassTokens = fullTokens.dropLast(1) + val packageClass = packageClassTokens.joinToString(".") + + val c = Class.forName(packageClass) + if (c.annotations.any { it.annotationClass == ShaderPhrases::class }) { + if (fieldName == "*") { + c.declaredFields.filter { println(it.type); it.type.name =="java.lang.String" }.map { + it.get(null) + }.joinToString("\n") + } else { + c.getDeclaredField(fieldName).get(null) + } + } else { + throw IllegalArgumentException("class $packageClass has no ShaderPhrases annotation") + } + } else { + it + } + } + return processed.joinToString("\n") +} \ No newline at end of file diff --git a/orx-shader-phrases/src/main/kotlin/annotations/ShaderPhrase.kt b/orx-shader-phrases/src/main/kotlin/annotations/ShaderPhrase.kt new file mode 100644 index 00000000..369e2a69 --- /dev/null +++ b/orx-shader-phrases/src/main/kotlin/annotations/ShaderPhrase.kt @@ -0,0 +1,15 @@ +package org.openrndr.extra.shaderphrases.annotations + +enum class ShaderPhraseLanguage { + GLSL +} + +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.FILE, AnnotationTarget.CLASS, AnnotationTarget.FIELD) +annotation class ShaderPhrase(val exports: Array, + val imports: Array = emptyArray(), + val language: ShaderPhraseLanguage = ShaderPhraseLanguage.GLSL) + + +@Target(AnnotationTarget.FILE) +annotation class ShaderPhrases(val exports: Array) \ No newline at end of file diff --git a/orx-shader-phrases/src/main/kotlin/phrases/Dummy.kt b/orx-shader-phrases/src/main/kotlin/phrases/Dummy.kt new file mode 100644 index 00000000..25bb86af --- /dev/null +++ b/orx-shader-phrases/src/main/kotlin/phrases/Dummy.kt @@ -0,0 +1,24 @@ +@file:JvmName("Dummy") +@file:ShaderPhrases(["dummy"]) + +package org.openrndr.extra.shaderphrases.phrases +import org.openrndr.extra.shaderphrases.annotations.ShaderPhrase +import org.openrndr.extra.shaderphrases.annotations.ShaderPhrases + +@ShaderPhrase(["dummy"]) +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)) + + + } +} \ No newline at end of file diff --git a/orx-shader-phrases/src/test/kotlin/TestPreprocessShader.kt b/orx-shader-phrases/src/test/kotlin/TestPreprocessShader.kt new file mode 100644 index 00000000..c6cc5f0f --- /dev/null +++ b/orx-shader-phrases/src/test/kotlin/TestPreprocessShader.kt @@ -0,0 +1,19 @@ +import org.openrndr.extra.shaderphrases.preprocessShader +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.specification.describe + +object TestPreprocessShader:Spek({ + + describe("A shader with import statements") { + val shader = """ +#version 330 +import org.openrndr.extra.shaderphrases.phrases.Dummy.* + + +""".trimIndent() + describe("when preprocessed") { + val processed = preprocessShader(shader) + println(processed) + } + } +}) \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 01422ade..5d157eca 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,23 +1,25 @@ rootProject.name = 'orx' include 'orx-camera', - 'orx-compositor', - 'orx-easing', - 'orx-file-watcher', - 'orx-filter-extension', - 'orx-integral-image', - 'orx-interval-tree', - 'orx-jumpflood', - 'orx-kdtree', - 'orx-mesh-generators', - 'orx-midi', - 'orx-no-clear', - 'orx-noise', - 'orx-obj-loader', - 'orx-olive', - 'orx-kinect-common', - 'orx-kinect-v1', - 'orx-kinect-v1-natives-linux-x64', - 'orx-kinect-v1-natives-macos', - 'orx-kinect-v1-natives-windows', - 'orx-kinect-v1-demo' + 'orx-compositor', + 'orx-easing', + 'orx-file-watcher', + 'orx-filter-extension', + 'orx-integral-image', + 'orx-interval-tree', + 'orx-jumpflood', + 'orx-kdtree', + 'orx-mesh-generators', + 'orx-midi', + 'orx-no-clear', + 'orx-noise', + 'orx-obj-loader', + 'orx-olive', + 'orx-shader-phrases', + 'orx-shader-phrases-processor', + 'orx-kinect-common', + 'orx-kinect-v1', + 'orx-kinect-v1-natives-linux-x64', + 'orx-kinect-v1-natives-macos', + 'orx-kinect-v1-natives-windows', + 'orx-kinect-v1-demo' \ No newline at end of file