A Kotlin Multiplatform library for GPU shader effects in Jetpack Compose, supporting Android, iOS, and Desktop (Windows, macOS, Linux). Apply stunning visual effects with a simple, type-safe API.
ShaderX is a cross-platform shader effects library that brings GPU-powered visual effects to Compose Multiplatform applications. It provides an intuitive Modifier-based API for applying effects like grayscale, blur, pixelation, and wave animations to any composable. Built using modern Kotlin Multiplatform development practices, it offers native performance across Android, iOS, and Desktop platforms.
| Android | iOS | Desktop |
|---|---|---|
| Coming Soon | Coming Soon | Coming Soon |
-
Cross-Platform Support
- ๐ค Android (API 33+ with AGSL)
- ๐ iOS (arm64, Simulator)
- ๐ฅ๏ธ Desktop (Windows, macOS, Linux with Skia)
-
Rich Effects Library
- ๐ซ๏ธ Blur - Hardware-accelerated Gaussian blur
- ๐จ Grayscale - Convert to grayscale using luminance weights
- ๐ธ Sepia - Apply vintage sepia tone
- ๐ฒ Pixelate - Create retro pixelation effects
- ๐ Vignette - Darken image edges
- ๐ Chromatic Aberration - Simulate lens color separation
- ๐ Invert - Invert all colors
- ๐ Wave - Animated wave distortion
- ๐ญ Gradient - Custom gradient overlays
-
Developer Experience
- ๐ Type-safe API with strongly typed parameters
- โก Compose Modifier extensions for easy integration
- ๐ฌ Built-in animation support
- ๐ ๏ธ Custom shader support (AGSL/SkSL)
- โ Comprehensive error handling with
ShaderResult<T> - ๐ Effect chaining with
CompositeEffect
Add the dependency to your build.gradle.kts:
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
// build.gradle.kts
dependencies {
implementation("com.github.Debanshu777.ShaderX:shaderx:0.1.1")
}Apply a simple effect:
import com.debanshu.shaderlab.shaderx.compose.shaderEffect
import com.debanshu.shaderlab.shaderx.effects.GrayscaleEffect
@Composable
fun GrayscaleImage() {
Image(
painter = painterResource("photo.png"),
contentDescription = null,
modifier = Modifier.shaderEffect(GrayscaleEffect())
)
}Use animated effects:
import com.debanshu.shaderlab.shaderx.compose.rememberShaderEffect
import com.debanshu.shaderlab.shaderx.effects.WaveEffect
@Composable
fun AnimatedWaveImage() {
val waveEffect = rememberShaderEffect(WaveEffect(amplitude = 10f))
Image(
painter = painterResource("photo.png"),
contentDescription = null,
modifier = Modifier.shaderEffect(waveEffect)
)
}Adjust parameters dynamically:
val effect = GrayscaleEffect(intensity = 0.5f)
val updatedEffect = effect.withParameter("intensity", 0.8f)| Effect | Description | Animated |
|---|---|---|
GrayscaleEffect |
Converts to grayscale using luminance weights | โ |
SepiaEffect |
Applies vintage sepia tone | โ |
VignetteEffect |
Darkens image edges with customizable radius | โ |
NativeBlurEffect |
Hardware-accelerated Gaussian blur | โ |
PixelateEffect |
Creates retro pixelation with adjustable block size | โ |
ChromaticAberrationEffect |
Simulates lens color separation | โ |
InvertEffect |
Inverts all color channels | โ |
WaveEffect |
Animated wave distortion effect | โ |
GradientEffect |
Custom gradient overlay | โ |
data class MyEffect(
private val intensity: Float = 1f
) : RuntimeShaderEffect {
override val id = "my_effect"
override val displayName = "My Effect"
override val shaderSource = """
uniform shader content;
uniform float intensity;
half4 main(float2 fragCoord) {
half4 color = content.eval(fragCoord);
return half4(color.rgb * intensity, color.a);
}
"""
override val parameters = listOf(
PercentageParameter("intensity", "Intensity", intensity)
)
override fun buildUniforms(width: Float, height: Float) = listOf(
FloatUniform("intensity", intensity)
)
override fun withParameter(id: String, value: Float) = when (id) {
"intensity" -> copy(intensity = value)
else -> this
}
}The library uses ShaderResult<T> for operations that may fail:
val factory = ShaderFactory.create()
val result = factory.createRenderEffect(effect, width, height)
result
.onSuccess { renderEffect ->
// Apply the effect
}
.onFailure { error ->
when (error) {
is ShaderError.CompilationError -> log("Shader compile failed: ${error.message}")
is ShaderError.UnsupportedEffect -> log("Effect not supported: ${error.effectId}")
is ShaderError.PlatformNotSupported -> log("Platform limitation: ${error.message}")
else -> log("Unknown error: ${error.message}")
}
}| Category | Technology | Version |
|---|---|---|
| Language | Kotlin | 2.3.0 |
| UI Framework | Compose Multiplatform | 1.10.0 |
| Build System | Gradle (AGP) | 9.0.0 |
| Android SDK | Compile/Target SDK | 36 |
| Coroutines | kotlinx-coroutines | 1.10.2 |
| Serialization | kotlinx-serialization | 1.9.0 |
| Platform | Shader Backend | Min Version |
|---|---|---|
| Android | AGSL (RuntimeShader) | API 33 |
| iOS | Skia | iOS 14+ |
| Desktop | Skia | JDK 11+ |
ShaderLab/
โโโ ๐ shaderx/ # Core library module
โ โโโ src/
โ โโโ ๐ commonMain/ # Shared Kotlin code
โ โ โโโ kotlin/com/debanshu/shaderlab/shaderx/
โ โ โโโ ShaderX.kt # Main entry point
โ โ โโโ ShaderConstants.kt # Shared constants
โ โ โโโ compose/ # Compose Modifier integration
โ โ โโโ effect/ # Core effect interfaces
โ โ โ โโโ ShaderEffect.kt
โ โ โ โโโ RuntimeShaderEffect.kt
โ โ โ โโโ AnimatedShaderEffect.kt
โ โ โ โโโ NativeEffect.kt
โ โ โ โโโ CompositeEffect.kt
โ โ โ โโโ impl/ # Built-in effect implementations
โ โ โโโ effects/ # Public effect APIs
โ โ โโโ factory/ # Platform-specific shader factories
โ โ โโโ parameter/ # Parameter types & formatting
โ โ โโโ uniform/ # Shader uniform types
โ โ โโโ result/ # Error handling (ShaderResult)
โ โโโ ๐ androidMain/ # Android-specific (AGSL)
โ โโโ ๐ iosMain/ # iOS-specific (Skia)
โ โโโ ๐ jvmMain/ # Desktop-specific (Skia)
โ โโโ ๐ skiaMain/ # Shared Skia implementation
โโโ ๐ samples/
โ โโโ ๐ ShaderLab/ # Demo application
โ โ โโโ composeApp/ # Shared compose code
โ โ โโโ androidApp/ # Android launcher
โ โ โโโ iosApp/ # iOS Xcode project
โ โ โโโ imagelib/ # Image loading utilities
โ โโโ ๐ VerticalCarousel/ # Additional sample
โโโ ๐ gradle/
โโโ libs.versions.toml # Version catalog
| Interface | Purpose |
|---|---|
ShaderEffect |
Base interface for all shader effects |
RuntimeShaderEffect |
Effects using custom AGSL/SkSL shaders |
AnimatedShaderEffect |
Effects with time-based animations |
NativeEffect |
Platform-native effects (e.g., hardware blur) |
CompositeEffect |
Chain multiple effects together |
# Build library for all platforms
./gradlew :shaderx:build
# Publish to local Maven
./gradlew :shaderx:publishToMavenLocal# Build debug APK
./gradlew :samples:ShaderLab:androidApp:assembleDebug
# Install on connected device
./gradlew :samples:ShaderLab:androidApp:installDebug# Build framework for simulator
./gradlew :samples:ShaderLab:composeApp:linkDebugFrameworkIosSimulatorArm64Then open samples/ShaderLab/iosApp/iosApp.xcodeproj in Xcode and run.
# Run directly
./gradlew :samples:ShaderLab:composeApp:run
# Package for distribution
./gradlew :samples:ShaderLab:composeApp:packageDmg # macOS
./gradlew :samples:ShaderLab:composeApp:packageMsi # Windows
./gradlew :samples:ShaderLab:composeApp:packageDeb # Linux- Additional effects (Glitch, Noise, Film Grain)
- Effect presets and themes
- Shader parameter animation curves
- Compose preview support
- Effect export/import (JSON)
- Shader hot-reload for development
- Web (WASM) support
- Video/camera effect support
Contributions are welcome! Please feel free to submit a Pull Request.
- Follow Kotlin coding conventions
- Use Compose best practices
- Maintain clean architecture principles
- Add appropriate test coverage
Copyright 2024 Debanshu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
- Built with Kotlin Multiplatform
- UI powered by Compose Multiplatform
- Android shaders using AGSL (Android Graphics Shading Language)
- Cross-platform rendering with Skia
ShaderX - GPU-powered visual effects across platforms ๐จโจ