Source Shader Editor - External input

From Valve Developer Community
Jump to: navigation, search

Shaders created through the editor can be affected by external data in three different ways. It's possible to define global information, instantly accessible in every shader, per material data that can be set in the vmt and per material data that can be defined at runtime through proxies or anything else.

Client callbacks

These callbacks can be adjusted in ShaderEditorSystem.cpp. The function void ShaderEditorHandler::RegisterCallbacks() will declare them globally for every shader by registering each callback through:

IVShaderEditor::RegisterClientCallback( const char *name, pFnClCallback(callback), int numComponents )

The first parameter defines the callback name which you will be able to see in the editor, it can be arbitrary. The second parameter requires you to pass a function pointer for the specific callback. This function will merely read the data from a struct which was updated earlier in void ShaderEditorHandler::PrepareCallbackData(), because the callback can be executed asynchronously from the shader or the editor library (for the 2D preview). The last parameter will influence the datatype of the callback node, it can be set to a value between 1 and 4, respectively influencing the amount of components your constant will have.

To access the callback function, create the Callback constant node which is located at New node -> Constants -> Callback constant in the context menu. When you open its properties, you can utilize the dropdown menu to select a callback. All callbacks that were registered by the client library will be visible there.

Note.png Note: Shaders will save the callback per name, so changing their names will break all shaders you have already created with the old name.

Vmt parameters

The node VParam static will allow you to define custom parameters for constants in your vmt, it is located at New node -> Constants -> VParam static. The values used there will only be read once. Changing them at runtime will not work, because these custom parameters don't exist inside the shader and can't be found with, for example, IMaterial::FindVar().

The properties dialog of this node will allow you to define a custom name for your parameter, set the datatype of your node and create default values in case the vmt does not define that parameter.

A static parameter with the datatype set to float3 and the name rim_color could look like this in the vmt:

"$rim_color" "[0.1 0.4 1]"

Mutable parameters

These material parameters are defined by the shader and can be accessed and changed at runtime. The node is located at New node -> Constants -> VParam mutable. If you open the properties dialog of this node, you can define which mutable parameter to read from and which datatype to expect.

For example, the first mutable parameter uses the hardcoded name MUTABLE_01. You will be able to access this material parameter from anywhere like usual. Assuming you have your IMaterial pointer, you can do the following to get it:

bool bFound = false;
IMaterialVar *pMutableVar = pMaterial->FindVar( "$MUTABLE_01", &bFound );

Changing it would then be as simple as doing:

if ( bFound )
	pMutableVar->SetVecValue( 0, 0, 0, 0 );

Mutable parameters are for example useful if you want to access per entity data in a shader, like the entities velocity or origin. Material proxies can be used for this purpose.

View render callbacks

Render callbacks are currently defined in ShaderEditorSystem.cpp aswell. They are used by the post processing node New node -> Render -> Render view. The function void ShaderEditorHandler::RegisterViewRenderCallbacks() will publish them to the editor by calling:

void IVShaderEditor::RegisterViewRenderCallback( const char *pszVrCName, pFnVrCallback(callback),
		const char **pszBoolNames = NULL, const bool *pBoolDefaults = NULL, const int numBoolParams = 0,
		const char **pszIntNames = NULL, const int *pIntDefaults = NULL, const int numIntParams = 0,
		const char **pszFloatNames = NULL, const float *pFloatDefaults = NULL, const int numFloatParams = 0,
		const char **pszStringNames = NULL, const char **pStringDefaults = NULL, const int numStringParams = 0 );

You are required to pass a name for the callback and a respective function pointer. The macro pFnVrCallback_Declare(NAME) helps you to define the signature of such a function. Optionally, you are able to pass a variable amount of parameters to the editor, which will be shown in the nodes properties dialog. Whatever you pass here will be available in arrays when the function is called, the size of the arrays will match the amount of parameters you passed through.
You can draw whatever you want during such a callback, the exampe functions provide rendering code for a general world view and the viewmodel.