[orx-shader-phrases] Add shader phrases tweaks (#196)
This commit is contained in:
@@ -88,6 +88,7 @@ kotlin {
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")
|
||||
runtimeOnly("org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion")
|
||||
runtimeOnly("org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion")
|
||||
runtimeOnly("org.slf4j:slf4j-simple:1.7.30")
|
||||
implementation("org.spekframework.spek2:spek-dsl-jvm:$spekVersion")
|
||||
implementation("org.amshove.kluent:kluent:$kluentVersion")
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.openrndr.extra.shaderphrases
|
||||
|
||||
import mu.KotlinLogging
|
||||
import org.openrndr.draw.Shader
|
||||
import org.openrndr.extra.shaderphrases.ShaderPhraseRegistry.getGLSLFunctionName
|
||||
//import org.openrndr.extra.shaderphrases.phrases.phraseTbnMatrix
|
||||
import org.openrndr.utils.url.textFromURL
|
||||
|
||||
@@ -16,16 +17,9 @@ class ShaderPhrase(val phrase: String) {
|
||||
* 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)
|
||||
val id = getGLSLFunctionName(phrase)
|
||||
val prefix = bookId?.let { "$it." } ?: ""
|
||||
ShaderPhraseRegistry.registerPhrase("$prefix$id", this)
|
||||
}
|
||||
}
|
||||
/**
|
||||
@@ -61,6 +55,22 @@ object ShaderPhraseRegistry {
|
||||
}
|
||||
return phrase
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first GLSL function name out of GLSL source code
|
||||
*/
|
||||
fun getGLSLFunctionName(glsl: String): String {
|
||||
val functionRex =
|
||||
Regex("""\s*(float|int|[bi]?vec[234]|mat[34])\s+(\w+)\s*\(.*\).*""")
|
||||
val defs = glsl.split("\n").filter {
|
||||
functionRex.matches(it)
|
||||
}.take(1).mapNotNull {
|
||||
val m = functionRex.find(it)
|
||||
m?.groupValues?.getOrNull(2)
|
||||
}
|
||||
return defs.firstOrNull()
|
||||
?: error("no function body found in phrase")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,10 +84,10 @@ fun preprocessShader(source: String, symbols: Set<String> = emptySet()): 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 funcName = Regex("""^\s*#pragma\s+import\s+([a-zA-Z0-9_.]+)""")
|
||||
val processed = lines.map { line ->
|
||||
if (line.contains("#pragma")) {
|
||||
val symbol = funcName.find(line)?.groupValues?.get(1) ?: return@map line
|
||||
val fullTokens = symbol.split(".")
|
||||
val fieldName = fullTokens.last().replace(";", "").trim()
|
||||
val packageClassTokens = fullTokens.dropLast(1)
|
||||
@@ -90,7 +100,7 @@ fun preprocessShader(source: String, symbols: Set<String> = emptySet()): String
|
||||
""
|
||||
}
|
||||
} else {
|
||||
it
|
||||
line
|
||||
}
|
||||
}
|
||||
return processed.joinToString("\n")
|
||||
|
||||
52
orx-shader-phrases/src/jvmTest/kotlin/TestFunctionNameRx.kt
Normal file
52
orx-shader-phrases/src/jvmTest/kotlin/TestFunctionNameRx.kt
Normal file
@@ -0,0 +1,52 @@
|
||||
import org.amshove.kluent.`should be equal to`
|
||||
import org.amshove.kluent.internal.assertFails
|
||||
import org.openrndr.extra.shaderphrases.ShaderPhraseRegistry.getGLSLFunctionName
|
||||
import org.spekframework.spek2.Spek
|
||||
import org.spekframework.spek2.style.specification.describe
|
||||
|
||||
object TestFunctionNameRx : Spek({
|
||||
describe("A function name") {
|
||||
|
||||
mapOf(
|
||||
"ivec4 aaa() {" to "aaa",
|
||||
"ivec3 bbb() {" to "bbb",
|
||||
"ivec2 ccc() {" to "ccc",
|
||||
"bvec4 ddd() {" to "ddd",
|
||||
"bvec3 eee() {" to "eee",
|
||||
"bvec2 fff() {" to "fff",
|
||||
"vec4 ggg() {" to "ggg",
|
||||
"vec3 hhh() {" to "hhh",
|
||||
"vec2 iii() {" to "iii",
|
||||
"mat3 jjj() {" to "jjj",
|
||||
"mat4 kkk() {" to "kkk",
|
||||
"float lll() {" to "lll",
|
||||
" float mmm( ) { " to "mmm",
|
||||
"int nnn() {" to "nnn",
|
||||
"vec2 limit(vec2 a, float b) {" to "limit",
|
||||
"""
|
||||
vec4 white() {
|
||||
return vec4(1.0);
|
||||
}
|
||||
""".trimMargin() to "white"
|
||||
).forEach { (goodGLSL, expectedFuncName) ->
|
||||
it("can be extracted from valid GLSL") {
|
||||
getGLSLFunctionName(goodGLSL) `should be equal to`
|
||||
expectedFuncName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe("A function name") {
|
||||
listOf(
|
||||
"float int mat4",
|
||||
"float rnd {",
|
||||
).forEach { badGLSL ->
|
||||
it("is not extracted if GLSL function not declared") {
|
||||
assertFails {
|
||||
val funcName = getGLSLFunctionName(badGLSL)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
@@ -6,10 +6,12 @@ import org.spekframework.spek2.style.specification.describe
|
||||
|
||||
object TestShaderPhrase : Spek({
|
||||
describe("A shader phrase") {
|
||||
val phrase = ShaderPhrase("""
|
||||
val phrase = ShaderPhrase(
|
||||
"""
|
||||
|vec4 test_phrase() {
|
||||
|}
|
||||
""".trimMargin() )
|
||||
""".trimMargin()
|
||||
)
|
||||
it("can be registered") {
|
||||
phrase.register()
|
||||
}
|
||||
|
||||
@@ -5,19 +5,23 @@ import org.openrndr.extra.shaderphrases.ShaderPhraseRegistry
|
||||
import org.spekframework.spek2.Spek
|
||||
import org.spekframework.spek2.style.specification.describe
|
||||
|
||||
class TestShaderPhraseBookobject : Spek({
|
||||
class TestShaderPhraseBook : Spek({
|
||||
describe("A shader phrase book") {
|
||||
val book = object:ShaderPhraseBook("testBook") {
|
||||
val phrase = ShaderPhrase("""
|
||||
|vec4 test_phrase() {
|
||||
|}
|
||||
""".trimMargin() )
|
||||
val book = object : ShaderPhraseBook("testBook") {
|
||||
val phrase = ShaderPhrase(
|
||||
"""
|
||||
vec4 test_phrase() {
|
||||
}
|
||||
""".trimMargin()
|
||||
)
|
||||
}
|
||||
it("can be registered") {
|
||||
book.register()
|
||||
}
|
||||
it("can be found") {
|
||||
ShaderPhraseRegistry.findPhrase("testBook.test_phrase") `should be` book.phrase
|
||||
ShaderPhraseRegistry.findPhrase(
|
||||
"testBook.test_phrase"
|
||||
) `should be` book.phrase
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,42 @@
|
||||
import org.amshove.kluent.`should contain`
|
||||
import org.amshove.kluent.`should not contain`
|
||||
import org.openrndr.extra.shaderphrases.ShaderPhrase
|
||||
import org.openrndr.extra.shaderphrases.ShaderPhraseBook
|
||||
import org.openrndr.extra.shaderphrases.preprocessShader
|
||||
import org.spekframework.spek2.Spek
|
||||
import org.spekframework.spek2.style.specification.describe
|
||||
|
||||
class TestShaderPhrasePreprocessing : Spek({
|
||||
describe("the glsl code") {
|
||||
val book = object : ShaderPhraseBook("testBook") {
|
||||
val phrase1 = ShaderPhrase("vec3 phrase1() { }")
|
||||
val phrase2 = ShaderPhrase("vec4 phrase2() { }")
|
||||
}
|
||||
book.register()
|
||||
|
||||
val glsl = """
|
||||
// test expected usage
|
||||
#pragma import testBook.phrase1
|
||||
// test odd spacing and line termination
|
||||
#pragma import testBook.phrase2;
|
||||
""".trimIndent()
|
||||
|
||||
val glslProcessed = preprocessShader(glsl)
|
||||
|
||||
it("should not contain phrase1 before preprocessing") {
|
||||
glsl `should not contain` book.phrase1.phrase
|
||||
}
|
||||
|
||||
it("should not contain phrase2 before preprocessing") {
|
||||
glsl `should not contain` book.phrase2.phrase
|
||||
}
|
||||
|
||||
it("should contain phrase1 after preprocessing") {
|
||||
glslProcessed `should contain` book.phrase1.phrase
|
||||
}
|
||||
|
||||
it("should contain phrase2 after preprocessing") {
|
||||
glslProcessed `should contain` book.phrase2.phrase
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user