RenderNode for Greater, Higher Blurs | by Chet Haase | Android Builders | Nov, 2022

RenderEffects #3: Utilizing RenderNode for sooner, higher blurring

The caption is drawn with a shader which each blurs and frosts that space

The rationale that the blur+frost impact isn’t simple comes right down to the truth that I solely wish to shade a part of that ImageView by which the enlarged image seems. That’s, I solely wish to blur/frost the label space on the backside, not all the view. RenderEffect, nonetheless, applies to the complete view; there is no such thing as a solution to crop the impact to only a portion of the view. So after I apply a RenderEffect blur after which the frosted-glass shader to the ImageView holding the enlarged image, with code like this:

val blur = RenderEffect.createBlurEffect(
30f, 30f, Shader.TileMode.CLAMP)
val shader = RenderEffect.createRuntimeShaderEffect(
val chain = RenderEffect.createChainEffect(blur, shader)
Making use of a RenderEffect blur to a view blurs all the view, which is… not what I wished

Okay, what about utilizing a separate View?

You would possibly fairly surprise (as I did when first engaged on the app) why I can’t merely depend on the view hierarchy to assist out. That’s, as an alternative of shading the label space within the bigger ImageView object, I might use a separate view sized to the caption bounds, sitting over the underside of the ImageView, similar to the prevailing TextView which holds the caption.

The caption impact is now being finished straight within the TextView. (But it surely’s not being finished effectively).
The caption impact accurately (shader utilized to underlying ImageView)

What I’d actually love to do (and what I attempted and did not do after I first wrote my demo app) is to chain results collectively. That’s, I’d like one RenderEffect utilizing the system blur, through RenderEffect.createBlurEffect(), the identical as I’m utilizing within the underlying picture gallery container. Then I desire a second impact to use a frosted-glass shader (with out additionally making use of the field blur that’s in my present shader), created with RenderEffect.createRuntimeShaderEffect(). Then I might composite these results utilizing RenderEffect.createChainedEffect(), to inform the system to use each results collectively, one after the opposite.

To cite from the reference docs on RenderNode:

RenderNodes are used internally for all Views by default and will not be sometimes used straight.

Oh no, wait — that’s not what I meant to stick (we’re principally undoubtedly going to make use of it straight). Right here, that is higher:

RenderNode is used to construct {hardware} accelerated rendering hierarchies.

Each View object, sooner or later earlier than its contents seem on the display, information the operations and attributes to attract its contents, for supply to the low-level renderer (Skia). It does this through RenderNode, which, as of API stage 29, is uncovered as public API that you should utilize straight. That’s, you may cache instructions in a RenderNode after which draw that node manually, sometimes to a View.

First, we create and cache two RenderNode objects, which will probably be reused (redrawn) every time the view itself is drawn:

val contentNode = RenderNode("picture")
val blurNode = RenderNode("blur")
override enjoyable onDraw(canvas: Canvas?) {

contentNode.setPosition(0, 0, width, top)
val rnCanvas = contentNode.beginRecording()


// ... remainder of code beneath

    // ... remainder of code above    blurNode.setRenderEffect(RenderEffect.createBlurEffect(30f, 30f,
blurNode.setPosition(0, 0, width, 100)
blurNode.translationY = top - 100f

val blurCanvas = blurNode.beginRecording()
blurCanvas.translate(0f, -(top - 100f))


Higher blur within the label by combining a RenderEffect blur along with frosted-glass shader, with two RenderNodes.

That is the top of this present collection (although I reserve the choice to put in writing extra shader and RenderEffect articles sooner or later. No guarantees). We managed to mess around with the system blur to get a blur-behind impact that helped pop a picture out from the background. Then we added AGSL shader logic to boost the visuals in a caption for the picture. Lastly, we used RenderNode to reap the benefits of the system blur for a greater (and sooner!) impact, and to simplify the AGSL shader logic to easily present the frosted-glass impact.

  • RenderEffect: The category used to create results for blurs, bitmaps, chains and extra. These results are set on Views or RenderNodes to alter the way in which these objects are drawn.
  • RenderNode: The thing which holds the underlying operations used to attract Views, however which will also be used on to document and retailer customized drawing operations.
  • RuntimeShader: The thing which holds the code for an AGSL shader.
  • AGSL: Android Graphics Shading Language. Like SkSL, however for Android. It supplies a mechanism for creating very customized per-pixel drawing results.
  • SkSL: The shading language for Skia. It’s like GLSL, however for the Skia rendering pipeline.
  • GLSL shaders: The language for fragment shaders when utilizing OpenGL.

Related Articles


Please enter your comment!
Please enter your name here

Latest Articles