MAXScript Tools and Interaction with 3ds Max > Creating MAXScript Tools > Scripted Plug-ins >

# Scripted RenderEffect Plug-ins

A scriptable RenderEffect plug-in can be declared by specifying the <superclass> as RenderEffect and by declaring an apply event handler. When declared, the render effect can be seen in Render Effects > Add dialog.

Event Handlers:

    on apply <bitmap> do <expr>

When the scripted effect is added as one of the rendering effects and "Update Scene" or "Update Effect" buttons are pressed, the apply event handler is called and passed a bitmap which can be modified with any changes the render effect wants to make. The bitmap you are given is the current rendered image that has had all of the prior effects in the render effects list applied to it. You modify this bitmap in place, typically by using the getPixel() and setPixel() functions. This modified bitmap is then passed onto the next render effect in the list or to the render output if it is the last effect.

To allow scripted Effects to take advantage of the g-buffer channel access, the following handlers are present:

    on channelsRequired do <expr>

The handler expression must evaluate to an array of the g-buffer channel names that are required. The g-buffer channel names are:

    #zDepth #matID #objectID #UVCoords #normal #unClamped #coverage #mask #node #shaderColor #shaderTransparency #velocity #weight

    on preApply <bitmap> do <expr>

The preApply handler allows the scripted effect to analyze the incoming render bitmap and its channels in order to precondition the delegate's effect processing.

So, you might add an on channelsRequired do to add #node and #coverage channels to the renderer’s bitmap, and an on preApply bm do to get the #node channel out as a mask and then set it into a delegate’s mask parameter to limit an effect to a given object.

The render() function can be called re-entrantly within scripted renderEffect. In releases prior to 3ds Max 4, attempting to do this caused a runtime error saying that the renderer could not be called while a render was already under way.

Here's a simple example that extends the Blur effect to add another rollout that has a node picker button. If you pick a node it generates a channel mask and uses that to limit the blur to that object:

SCRIPT
    plugin RenderEffect myBlurFX
    name:"Super Blur FX"
    classID:#(6545,456581)
    extends:Blur
    version:1
    (
      local tx, cm, g_channels
      local tx = bitmaptexture ()
      local g_channels = #(#node, #coverage)
      rollout params "SupaFX Parameters"
      (
        label nn align:#center
        pickbutton nodepick "Pick Node"
      )
      parameters main rollout:params
      (
        thenode type:#node ui:nodepick
        on thenode set nd do
          params.nn.text = if nd == undefined then "" else nd.name
      )
      on channelsRequired do g_channels
      on preApply map do if theNode != undefined then
      (
        if cm == undefined then
        (
          cm = getChannelAsMask map #node node:theNode \
          fileName:(scriptsPath + "__fxtmp.bmp")
          save cm
          tx.bitmap = cm
        )
        else
          getChannelAsMask map #node node:theNode to:cm
      )
      on create do
      (
        delegate.selMaskActive = true
        delegate.selImageActive = false
        delegate.selMaskMap = tx
      )
    )

SCRIPT
    plugin renderEffect myColorBalanceFx
    name:"Super Color Balance FX"
    classID:#(64425,45761)
    extends:Color_Balance version:1
    (
      parameters main rollout:params
      (
        redness type:#integer animatable:true ui:redness default:0.0
        on redness set val do delegate.red = val
      )
      rollout params "Super Color Balance Parameters"
      (
        spinner redness "Redness: " type:#integer range:[-100,100,0]
      )
    )

SCRIPT
    plugin renderEffect Negative
    name:"Negative"
    classID:#(0xb7aa794c, 0xc3bd78ab)
    (
      parameters main rollout:params
      (
        Color type:#color default:blue ui:Color
      )
      rollout params "Negative Parameters"
      (
        colorpicker Color "Base color: " align:#center
      )
      on apply bmp do
      (
        for h=0 to (bmp.height-1) do
        (
          local sline = getPixels bmp [0,h] bmp.width
          for i=1 to sline.count do sline[i] = Color - sline[i]
          setPixels bmp [0,h] sline
        )
      )
    )

#### See Also

- RenderEffect Progress Callback Mechanism

- Updating Scripted Plug-ins

- Scripted Plug-in Methods

- Scripted Plug-in Clauses

- Scripted Plug-ins

- How To ... Create a MonoChrome RenderEffect