CompShader: Server basics

From The Foundry MODO SDK wiki
Jump to: navigation, search

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

Sample methods

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 packages.

        LxResult
csh_SetupChannels (
        ILxUnknownID		 addChan)
{
        CLxUser_AddChannel	 ac (addChan);

        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.

        LxResult
csh_LinkChannels (
        ILxUnknownID		 eval,
        ILxUnknownID		 item)
{
        CLxUser_Evaluation	 ev (eval);

        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.

        LxResult
csh_ReadChannels (
        ILxUnknownID		 attr,
        void		       **ppvData)
{
        CLxUser_Attributes	 at (attr);
        RendData		*rd = new RendData;

        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)

void

csh_Evaluate (
       ILxUnknownID            vector,
	ILxUnknownID		rayObj,
       LXpShadeComponents     *sCmp,
       LXpShadeOutput         *sOut,
       void                    *data)
{
        RendData		*rd = (RendData *) data;

	raycast.set (rayObj);

	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.

	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.

	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)

	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.

	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

In this example, USE_LOCATOR means that the shader will be automatically created a with a texture locator attached to it.

      int
csh_Flags) (
	LXtObjectID		 self)
{
       return LXfSHADERFLAGS_USE_LOCATOR;
}