KraftEffectTextureView
KraftEffectTextureView
extends KraftTextureView to provide a convenient way to apply shader effects to images and other content.
Overview
KraftEffectTextureView
is designed for applying shader effects to content. It builds on the OpenGL rendering capabilities of KraftTextureView
and adds functionality specifically for managing effects and controlling when rendering occurs.
This view is ideal for applications that need to apply visual effects to images or other content, with support for both one-time rendering and on-demand updates when effect parameters change.
Key Features
- Manages an
EffectExecution
instance that defines the visual effect to be applied - Provides methods to set and update effects
- Supports on-demand rendering when effect parameters change
- Handles aspect ratio adjustments for proper content display
- Automatically re-renders when the view size changes (configurable)
Basic Usage
Here's a simple example of using KraftEffectTextureView
to apply a saturation effect to an image:
class MyActivity : AppCompatActivity() {
private lateinit var effectView: KraftEffectTextureView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Create the view
effectView = KraftEffectTextureView(this)
setContentView(effectView)
// Load an image and apply a saturation effect
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.my_image)
effectView.setEffect(
effectExecutionProvider = { windowSurface ->
// Create a pipeline with a saturation shader
pipeline(windowSurface) {
serialSteps(
inputTexture = bitmap.asTexture(),
targetBuffer = windowSurface
) {
step(SaturationKraftShader()) { shader ->
shader.saturation = 1.5f // Increase saturation
}
}
}
}
)
}
override fun onDestroy() {
// Clean up resources
effectView.terminate()
super.onDestroy()
}
}
Important Methods
setEffect
The primary method for configuring the effect to be applied:
fun setEffect(
afterSet: suspend GlEnvDslScope.(windowSurface: WindowSurfaceBuffer) -> Unit = {},
effectExecutionProvider: EffectExecutionProvider
)
This method:
- Takes an
EffectExecutionProvider
that creates the effect execution pipeline - Optionally accepts an
afterSet
lambda that runs after the effect is set - Typically used with the pipeline DSL to create a rendering pipeline
requestRender
Triggers a render with the current effect:
fun requestRender()
Call this method when you've changed effect parameters and want to update the display.
Properties
renderOnSizeChange
Controls whether rendering is automatically triggered when the view size changes:
var renderOnSizeChange: Boolean = true
ratio
Sets the aspect ratio of the view (width/height):
var ratio: Float = 0.0f
When set to a non-zero value, the view will maintain this aspect ratio during layout.
Example: Adjustable Effect
This example shows how to create an effect with parameters that can be adjusted dynamically:
class MyEffectActivity : AppCompatActivity() {
private lateinit var effectView: KraftEffectTextureView
private var saturation = 1.0f
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_effect)
effectView = findViewById(R.id.effect_view)
val saturationSeekBar = findViewById<SeekBar>(R.id.saturation_seekbar)
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.my_image)
// Set the aspect ratio based on the bitmap dimensions
effectView.ratio = bitmap.width.toFloat() / bitmap.height
// Set up the effect
effectView.setEffect(
effectExecutionProvider = { windowSurface ->
pipeline(windowSurface) {
serialSteps(
inputTexture = bitmap.asTexture(),
targetBuffer = windowSurface
) {
step(SaturationKraftShader()) { shader ->
shader.saturation = saturation
}
}
}
}
)
// Update saturation when the seek bar changes
saturationSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
saturation = progress / 100f * 2f // Range: 0 to 2
effectView.requestRender() // Request a render with the new saturation
}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onStopTrackingTouch(seekBar: SeekBar) {}
})
}
}
Considerations
- Effects are applied asynchronously in a coroutine context
- Always call
requestRender()
after changing effect parameters - For animated effects that change over time, consider using AnimatedKraftTextureView instead
- The view automatically handles OpenGL context management, but you should still call
terminate()
when done
Next Steps
For animated effects that change over time, see AnimatedKraftTextureView.