[orx-dnk3] Add feature architecture and post processing effects
This commit is contained in:
@@ -16,6 +16,7 @@ class PhraseResource<R>(private val resourceUrl: String) : ReadOnlyProperty<R, S
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* PhraseResource delegate builder function
|
||||
*/
|
||||
fun phraseResource(resource: String) : PhraseResource<Any?> {
|
||||
|
||||
@@ -9,50 +9,56 @@ import org.openrndr.extra.shaderphrases.annotations.ShaderPhrases
|
||||
* @param source GLSL source code encoded as string
|
||||
* @return GLSL source code with injected shader phrases
|
||||
*/
|
||||
fun preprocessShader(source: String): String {
|
||||
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 full = tokens[2]
|
||||
val fullTokens = full.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(".")
|
||||
|
||||
try {
|
||||
/* Note that JVM-style reflection is used here because of short-comings in the Kotlin reflection
|
||||
if (symbol !in newSymbols) {
|
||||
newSymbols.add(symbol)
|
||||
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 = c.getMethod(methodName).invoke(null) as String
|
||||
result
|
||||
} catch (e: NoSuchMethodException) {
|
||||
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 {
|
||||
result = c.getDeclaredField(fieldName).get(null) as String
|
||||
result
|
||||
} catch (e: NoSuchFieldException) {
|
||||
error("field \"$fieldName\" not found in \"#pragma import $packageClass.$fieldName\" on line ${index + 1}")
|
||||
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) {
|
||||
error("field \"$fieldName\" not found in \"#pragma import $packageClass.$fieldName\" on line ${index + 1}")
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
} else {
|
||||
throw IllegalArgumentException("class $packageClass has no ShaderPhrases annotation")
|
||||
}
|
||||
} else {
|
||||
throw IllegalArgumentException("class $packageClass has no ShaderPhrases annotation")
|
||||
} catch (e: ClassNotFoundException) {
|
||||
error("class \"$packageClass\" not found in \"#pragma import $packageClass\" on line ${index + 1}")
|
||||
}
|
||||
} catch (e: ClassNotFoundException) {
|
||||
error("class \"$packageClass\" not found in \"#pragma import $packageClass\" on line ${index + 1}")
|
||||
} else {
|
||||
""
|
||||
}
|
||||
} else {
|
||||
it
|
||||
@@ -67,6 +73,6 @@ fun preprocessShader(source: String): String {
|
||||
* @param url url pointing to GLSL shader source
|
||||
* @return GLSL source code with injected shader phrases
|
||||
*/
|
||||
fun preprocessShaderFromUrl(url: String): String {
|
||||
return preprocessShader(codeFromURL(url))
|
||||
fun preprocessShaderFromUrl(url: String, symbols: Set<String>): String {
|
||||
return preprocessShader(codeFromURL(url), symbols)
|
||||
}
|
||||
@@ -4,6 +4,7 @@ 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])
|
||||
@@ -19,15 +20,23 @@ float viewToProjectionDepth(float viewDepth, mat4 projection) {
|
||||
"""
|
||||
|
||||
/**
|
||||
* phrase for conversion from view to projection depth
|
||||
* 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 * projectionInverse[2].z + projectionInverse[3].z;
|
||||
float w = projectionDepth * projectionInverse[2].w + projectionInverse[3].w;
|
||||
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;
|
||||
}
|
||||
"""
|
||||
|
||||
13
orx-shader-phrases/src/main/kotlin/phrases/NormalMapping.kt
Normal file
13
orx-shader-phrases/src/main/kotlin/phrases/NormalMapping.kt
Normal file
@@ -0,0 +1,13 @@
|
||||
@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()
|
||||
Reference in New Issue
Block a user