CompShader: Server basics

A CompShader is plug-in server that implements a component shader.

Overview

Component shaders are used to take a a shader input, change its components and produce a new shader output. It can be useful if your shader only needs to change parts of the shading computation.

Headers

shade (lx-shade.hpp) * CLxImpl_CompShader action (lx-action.hpp) * CLxUser_Evaluation package (lx-package.hpp) * CLxUser_AddChannel value (lx-value.hpp) * CLxUser_Attributes vector (lx-vector.hpp) * CLxUser_PacketService

The plug-in server class derives from CLxImpl_CompShader, and exports the ILxCompShader interface. For speed purposes the class will also want to keep the packet service ready to hand.

CLxUser_PacketService pkt_service;

CompShader::SetupChannels()

Like a package, a value texture server must define its channels. The SetupChannels() method is identical to the one used by Package: Server basics.

1
2
3
4
5
         LxResult
 csh_SetupChannels (
         ILxUnknownID            addChan)
 {
         CLxUser_AddChannel      ac (addChan);
1
2
3
4
         ac.NewChannel ("myInput", "percent");
         ac.SetDefault (1.0, 1);
         return LXe_OK;
 }

CompShader::LinkChannels()

The value texture reads its channel values in a modifier context. That means that it has to declare the channels it wants to read using the Evaluation Interface. This is also a good place to cache the offsets for any vector packets that it wants to read.

1
2
3
4
5
6
         LxResult
 csh_LinkChannels (
         ILxUnknownID            eval,
         ILxUnknownID            item)
 {
         CLxUser_Evaluation      ev (eval);
1
2
3
         idx_value = ev.AddChan (item, "myInput");
         return LXe_OK;
 }

CompShader::ReadChannels()

Linking channels occurs once as items are added or their relationships are changed. Reading channels then happens any time channel values change. For example changing time may cause channels to be read again if they are animated. Values are read from an Attributes Interface using the index cached when linking channels. The values are then stored in an allocated data structure which is returned from the method.

1
2
3
4
5
6
7
         LxResult
 csh_ReadChannels (
         ILxUnknownID            attr,
         void                  **ppvData)
 {
         CLxUser_Attributes      at (attr);
         RendData               *rd = new RendData;
1
2
3
4
         rd->value  = at.Float (idx_value);
         ppvData[0] = rd;
         return LXe_OK;
 }

CompShader::Evaluate()

Shader evaluation is the second and final step of the evaluation, it is intended to read the material attributes from a sample vector packet and produce shading components. In this silly example we just replace the diffuse shading component with our custom color (red in this case)

1
2
3
4
5
6
7
8
9
        void
 csh_Evaluate (
        ILxUnknownID            vector,
        ILxUnknownID            rayObj,
        LXpShadeComponents     *sCmp,
        LXpShadeOutput         *sOut,
        void                    *data)
 {
         RendData               *rd = (RendData *) data;
1
        raycast.set (rayObj);
1
2
3
4
5
        for (i=0;i<3;i++) {
               sCmp->diff[i]  = pack->color[i];
               sOut->color[i] = sCmp->diff[i] + sCmp->spec[i] + sCmp->refl[i] + sCmp->tran[i] + sCmp->subs[i] + sCmp->lumi[i];
        }
 }

CompShader::SetShadeFlags()

This is used to set the shader evaluation flags (LXfSURF_). In this example the shader sets the visibility flags so that the surface becomes visible for reflection and refraction rays.

1
2
3
4
5
6
7
        LxResult
 csh_SetShadeFlags) (
        LXtObjectID              self,
        LXpShadeFlags           *sFlg)
 {
        sFlg->flags |= LXfSURF_VISREFL  | LXfSURF_VISREFR;
 }

CompShader::SetOpaque()

Opaque shaders are shaders that completely override the shaders below them, for example a shader that would set a constant value doesn’t need the computation from previous shaders. This flag is used as a way to optimize the shaders by ignoring the ones that are not used. In general comp shaders should not be opaque.

1
2
3
4
5
6
7
        LxResult
 csh_SetOpaque) (
        LXtObjectID              self,
        int                     *opaque)
 {
        return 0;
 }

CompShader::CustomPacket()

Shaders may need to use a custom packet to store their attributes. This method returns the packet name (if any)

1
2
3
4
5
6
7
        LxResult
 csh_CustomPacket) (
        LXtObjectID              self,
        const char              **packet)
 {
        packet[0] = "MyPacket";
 }

CompShader::Cleanup()

This is called at the end of rendering when the shader is destroyed.

1
2
3
4
5
6
7
        void
 csh_Cleanup) (
        LXtObjectID              self,
        void                    *data)
 {
        return;
 }

CompShader::Flags()

This is used to return a set of shader flags such as these ones

  • LXfSHADERFLAGS_USE_LOCATOR

  • LXfSHADERFLAGS_USE_CLIP

  • LXfSHADERFLAGS_USE_LIGHT

  • LXfSHADERFLAGS_USE_GROUP

1
2
3
4
5
6
       int
 csh_Flags) (
        LXtObjectID              self)
 {
        return LXfSHADERFLAGS_USE_LOCATOR;
 }