Creating a simple channel shader plugin

Note: applicable to R19 and earlier versions. Some code may be applicable to later versions of C4D.

The plugin source code has been updated to build with VS 2015 and the C4D R19 SDK. It is possible to use earlier SDKs but you may need to alter some function and variable names/definitions.

Introduction

As with any new plugin in C4D, I find it best to start off with one that already works and modify it as needed. In most cases you should be able to find a pluginin the SDK examples which will fit the bill. In this case, I wanted to write a plugin which would flip, or mirror, a bitmap horizontally.

(Why would you want to do this? Doesn’t the layer shader provide that functionality? Well, yes it does, but only for the user of C4D, not the programmer. If you need, as I did, to add a bitmap to a material then mirror it, you find that the SDK does not expose the layer shader, so you just can’t do it. In my case the only solution I could think of was to write my own shader to do the job.)

The best SDK example for this is the bitmap distortion shader, so you can use that as a start and not have to modify that much code.

Interface

The best way to start any plugin is to provide a basic interface. You can always change this later, but without the user interface you can’t really see if your plugin is working. I wanted the interface for this shader to have three gadgets: two check boxes to let the user select the mirroring option (horizontal or vertical), and a link box to hold the bitmaps the user chooses. The aim was for it to look like this:

Shader interface

 Since the resource editor can’t create description files for shaders, tool plugins and so on, we have to write this manually. The gadgets are all well-documented in the SDK, so my description file, which is very simple, is this:

CONTAINER Xbmflip
{
    NAME Xbmflip;

    INCLUDE Mpreview;
    INCLUDE Xbase;

    GROUP ID_SHADERPROPERTIES
    {
        SHADERLINK BMFLIPSHADER_TEXTURE { }
        BOOL BMFLIPSHADER_FLIPX { }
        BOOL BMFLIPSHADER_FLIPY { }
    }
}

I won’t bother explaining this; it’s all in the SDK. The file is a text file and saved as ‘xbmflip.res’ into the folder ‘res/description’ in the plugin folder.

Next, we want to be able to access the gadgets from code, so we have to provide identifiers for each gadget. This is done in the corresponding header to the resource file, and is as follows:

#ifndef _Xbmflip_H_
#define _Xbmflip_H_

enum
{
    BMFLIPSHADER_TEXTURE = 1000,
    BMFLIPSHADER_FLIPX = 1010,
    BMFLIPSHADER_FLIPY = 1020
};

#endif

This just assigns an ID value to each gadget. The file is saved as ‘xbmflip.h’, again into the folder ‘res/description’.

This works okay, but if used as it is wouldn’t be very user-friendly because in the interface there would be no text to identify what each gadget is for. For that, we have to add a text string for each gadget which needs one. We do this by creating another text file, called ‘xbmflip.str’, which should be saved into the folder ‘res/strings_us/description’. (These filenames are important, by the way. C4D will load the appropriate resource files automatically as long as we tell it the name of the file, which is common to each one – the .res, .h, and .str files.)

Also note that if you are using a non-English language version of C4D, the xbmflip.str file should be saved into the appropriate localized folder for your installation, such as ‘res/strings_de/description’ for German-language versions.

In this case the string file looks like this:

STRINGTABLE Xbmflip
{
    Xbmflip "Bitmap Transform Shader";
    BMFLIPSHADER_FLIPX   "Mirror X-axis";
    BMFLIPSHADER_FLIPY   "Mirror Y-axis";
    BMFLIPSHADER_TEXTURE "Texture";
}

Note that in this case there is one string for each identifier in the xbmflip.h file, but that needn’t always be the case, depending on the interface you’re creating. Not all gadgets will have strings, for example.

We still need to create two more text files to complete the interface. The first contains strings which are not specific to one description (or dialog box, if we had one). The only example in this case is the plugin name, which will appear in the material editor as one of the shaders the user can insert into a channel. This is what I tend to think of as a ‘global’ string, and these go into a file called c4d_string.str, which is saved into the folder ‘res/strings_us’ (or ‘res/strings_de’ or whatever language you use).

The file ‘c4d_strings’ is very short in this plugin:

// C4D-StringResource
// Identifier        Text

STRINGTABLE
{
    IDS_BMFLIP       "Bitmap Transform";
}

We can see from this that the identifier ‘IDS_BMFLIP’ is an index into this file and will retrieve the string which we will use as the plugin name. But where does that identifier come from? Because these are global strings, we can’t put the identifier in the xbmflip.h file, and we have to provide a separate header file for them. This is the file ‘c4d_symbols.h’ which is located in the ‘res’ folder. In this case it looks like this:

enum
{
    // string table definitions
    IDS_BMFLIP = 10000,

    // End of symbol definition
    _DUMMY_ELEMENT_
};

The syntax of this file is quite specific and I would recommend modifying an existing one rather than creating one from scratch.

So, finally we have a complete interface definition! The file structure should be as follows:

File structure

On the next page, we can actually start coding this plugin.

Page last updated June 23rd 2021