If the data is separate for each shader instance, it can be created in the init shader and attached to the shader instance itself. This is the recommended method for preprocessing shader parameters into a form that simplifies later shader calls during rendering. For example, if a shader parameter specifies an angle in radians or degrees, converting the angle to the cosine of the angle once in advance can save millions of expensive cosine computations in the main body of the shader. Here is an example:
DLLEXPORT void myshader_init( /* init shader */ miState *state, struct myshader *paras, miBoolean *inst_req) { if (!paras) *inst_req = miTRUE; else { struct mystruct **mydata; mi_query(miQ_FUNC_USERPTR, state, 0, &mydata); *mydata = mi_mem_allocate(...); (*mydata)->cos_angle = cos(*mi_eval_scalar(¶s->angle)); ... } } DLLEXPORT void myshader_exit( /* exit shader */ miState *state, struct myshader *paras) { if (paras) { struct mystruct **mydata; mi_query(miQ_FUNC_USERPTR, state, 0, &mydata); mi_mem_release(*mydata); } return(miTRUE); } DLLEXPORT void myshader( /* main shader */ miState *state, struct myshader *paras) { struct mystruct **mydata; mi_query(miQ_FUNC_USERPTR, state, 0, &mydata); ...use (*mydata)->cos_angle... return(miTRUE); }
Note that the init shader first requests instance initializations by setting inst_req to miTRUE, and creating the instance data for each instance initialization, indicated by a nonzero paras pointer. (Refer to page shaderinit for information on the difference between shader initialization and shader instance initialization.) Similarly, the exit instance shader deletes the data.
Note that this relies on the angle shader parameter to be constant. It is obtained only once with mi_eval_scalar, so this parameter cannot be attached to another shader that computes a new angle for each shader call. Since this is often desirable, the example above is a bit contrived.
Copyright © 1986-2009 by mental images GmbH