Added WIP shader-phrases, annotations and tooling for shader phrases

resolving is done using the JVM class loader
This commit is contained in:
Edwin Jakobs
2019-08-23 16:46:24 +02:00
parent 3c162f30d4
commit 98baf2a4c3
8 changed files with 134 additions and 7 deletions

View File

@@ -10,7 +10,7 @@ buildscript {
plugins { plugins {
// plugin dependencies, load without applying them // 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 'com.jfrog.artifactory' version '4.6.2' apply false
id 'nebula.contacts' version '4.1.1' apply false id 'nebula.contacts' version '4.1.1' apply false
@@ -38,7 +38,7 @@ plugins {
project.ext { project.ext {
openrndrVersion = "0.3.35" openrndrVersion = "0.3.35"
kotlinVersion = "1.3.41" kotlinVersion = "1.3.50"
spekVersion = "2.0.6" spekVersion = "2.0.6"
} }
@@ -65,16 +65,14 @@ allprojects {
repositories { repositories {
mavenCentral() mavenCentral()
jcenter()
maven { maven {
url = "https://dl.bintray.com/openrndr/openrndr" url = "https://dl.bintray.com/openrndr/openrndr"
} }
maven { maven {
url "https://dl.bintray.com/spekframework/spek" url "https://dl.bintray.com/spekframework/spek"
} }
} }
dependencies { dependencies {
@@ -82,11 +80,12 @@ allprojects {
compile "org.openrndr:openrndr-filter:$openrndrVersion" compile "org.openrndr:openrndr-filter:$openrndrVersion"
compile "org.openrndr:openrndr-shape:$openrndrVersion" compile "org.openrndr:openrndr-shape:$openrndrVersion"
compile group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.3.0-RC2' compile group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.3.0-RC2'
testImplementation "org.spekframework.spek2:spek-dsl-jvm:$spekVersion" testImplementation "org.spekframework.spek2:spek-dsl-jvm:$spekVersion"
testImplementation "org.amshove.kluent:kluent:1.53"
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"
runtime "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
} }
contacts { contacts {

3
orx-noise/build.gradle Normal file
View File

@@ -0,0 +1,3 @@
dependencies {
implementation project(":orx-shader-phrases")
}

View File

@@ -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()

View File

@@ -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")
}

View File

@@ -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<String>,
val imports: Array<String> = emptyArray(),
val language: ShaderPhraseLanguage = ShaderPhraseLanguage.GLSL)
@Target(AnnotationTarget.FILE)
annotation class ShaderPhrases(val exports: Array<String>)

View File

@@ -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))
}
}

View File

@@ -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)
}
}
})

View File

@@ -14,4 +14,6 @@ include 'orx-camera',
'orx-no-clear', 'orx-no-clear',
'orx-noise', 'orx-noise',
'orx-obj-loader', 'orx-obj-loader',
'orx-olive' 'orx-olive',
'orx-shader-phrases',
'orx-shader-phrases-processor'