Skip to content

Commit

Permalink
Add holo foil shader modifier (broken)
Browse files Browse the repository at this point in the history
  • Loading branch information
rock3r committed Oct 10, 2023
1 parent 23984c7 commit 99db1e8
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import java.io.InputStream

abstract class JewelResourceLoader : ResourceLoader {

private var verbose = true
private val verbose = true

protected fun loadResourceOrNull(path: String, classLoaders: List<ClassLoader>): InputStream? {
for (classLoader in classLoaders) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,10 @@ suspend fun retrieveTextStyle(
fontStyle: FontStyle = FontStyle.Normal,
size: TextUnit = TextUnit.Unspecified,
): TextStyle {
val font = (UIManager.getFont(key) ?: keyNotFound(key, "Font"))
.let { JBFont.create(it, false) }
val font = JBFont.create(
UIManager.getFont(key) ?: keyNotFound(key, "Font"),
false,
)

val derivedFont = font.let { if (bold) it.asBold() else it.asPlain() }
.let { if (fontStyle == FontStyle.Italic) it.asItalic() else it }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package org.jetbrains.jewel.samples.ideplugin.releasessample

import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asComposeRenderEffect
import androidx.compose.ui.graphics.graphicsLayer
import org.intellij.lang.annotations.Language
import org.jetbrains.skia.ImageFilter
import org.jetbrains.skia.RuntimeEffect
import org.jetbrains.skia.RuntimeShaderBuilder

@Language("GLSL") // Technically, SkSL
private const val FOIL_SHADER_CODE = """
const float STRENGTH = 0.4; // 0.0 = no effect, 1.0 = full effect
const float SATURATION = 0.9; // Color saturation (0.0 = grayscale, 1.0 = full color)
const float LIGHTNESS = 0.65; // Color lightness (0.0 = black, 1.0 = white)
uniform shader content; // Input texture (the application canvas)
uniform vec2 resolution; // Size of the canvas
uniform vec2 offset; // Additional offset of the effect
vec4 rainbowEffect(vec2 uv, vec2 offset) {
vec4 srcColor = content.eval(uv);
if (srcColor.a == 0.0) return srcColor;
float hue = uv.x / (1.75 + abs(offset.x)) + offset.x / 3.0;
float lightness = LIGHTNESS + 0.25 * (0.5 + offset.y * (0.5 - uv.y));
hue = fract(hue);
float c = (1.0 - abs(2.0 * lightness - 1.0)) * SATURATION;
float x = c * (1.0 - abs(mod(hue / (1.0 / 6.0), 2.0) - 1.0));
float m = LIGHTNESS - c / 2.0;
vec3 rainbowPrime;
if (hue < 1.0 / 6.0) {
rainbowPrime = vec3(c, x, 0.0);
} else if (hue < 1.0 / 3.0) {
rainbowPrime = vec3(x, c, 0.0);
} else if (hue < 0.5) {
rainbowPrime = vec3(0.0, c, x);
} else if (hue < 2.0 / 3.0) {
rainbowPrime = vec3(0.0, x, c);
} else if (hue < 5.0 / 6.0) {
rainbowPrime = vec3(x, 0.0, c);
} else {
rainbowPrime = vec3(c, 0.0, x);
}
vec3 rainbow = rainbowPrime + m;
return mix(srcColor, vec4(rainbow, srcColor.a), STRENGTH);
}
vec4 chromaticAberration(vec2 uv, vec2 offset) {
vec4 srcColor = rainbowEffect(uv, offset);
vec2 shift = offset * vec2(3.0, 5.0) / 1000.0;
vec4 leftColor = rainbowEffect(uv - shift, offset);
vec4 rightColor = rainbowEffect(uv + shift, offset);
return vec4(rightColor.r, srcColor.g, leftColor.b, srcColor.a);
}
vec4 main(float2 fragCoord) {
return chromaticAberration(fragCoord.xy, offset);
}
"""

private val runtimeEffect = RuntimeEffect.makeForShader(FOIL_SHADER_CODE)
private val shaderBuilder = RuntimeShaderBuilder(runtimeEffect)

internal fun Modifier.holoFoil(offset: Float) =
graphicsLayer {
shaderBuilder.uniform("resolution", size.width, size.height)
shaderBuilder.uniform("offset", 0f, offset)
clip = true

renderEffect =
ImageFilter.makeRuntimeShader(
runtimeShaderBuilder = shaderBuilder,
shaderNames = arrayOf("content"),
inputs = arrayOf(null),
).asComposeRenderEffect()
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package org.jetbrains.jewel.samples.ideplugin.releasessample

import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.background
Expand Down Expand Up @@ -88,6 +94,7 @@ import org.jetbrains.skiko.DependsOnJBR
import java.awt.Font
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import kotlin.time.Duration.Companion.seconds

@OptIn(DependsOnJBR::class)
@Composable
Expand Down Expand Up @@ -187,7 +194,6 @@ fun LeftColumn(
modifier = Modifier.fillMaxHeight().align(Alignment.CenterEnd),
)
}

}
}

Expand Down Expand Up @@ -447,11 +453,21 @@ fun RightColumn(
val imagePath = selectedItem.imagePath
if (imagePath != null) {
val painter = painterResource(imagePath, LocalResourceLoader.current)
val transition = rememberInfiniteTransition("HoloFoil")
val offset by transition.animateFloat(
initialValue = -1f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
tween(durationMillis = 2.seconds.inWholeMilliseconds.toInt(), easing = LinearEasing),
repeatMode = RepeatMode.Reverse,
),
)
Image(
painter = painter,
contentDescription = null,
modifier = Modifier.fillMaxWidth()
.sizeIn(maxHeight = 200.dp),
.sizeIn(maxHeight = 200.dp)
.holoFoil(offset),
contentScale = ContentScale.Fit,
)
}
Expand Down

0 comments on commit 99db1e8

Please sign in to comment.