/* Shader make_indexed_framebuffers Define mental ray framebuffers in version 3.6.x using a geometry shader to modify the options block. For example: instance "framebuffer_creation" geometry "make_indexed_framebuffers" ( "option_block_name" "options", "framebuffers" [ { "index" 0, "type" "+rgba", "filename" "buffer_0.tif" }, { "index" 1, "type" "+rgba", "filename" "buffer_1.tif" }, { "index" 2, "type" "+rgba", "filename" "buffer_2.tif" } ] ) end instance */ /* For sprintf in Windows: */ #define _CRT_SECURE_NO_WARNINGS #include #include #include "shader.h" #include "geoshader.h" /* Input parameter for each framebuffer is a struct: */ typedef struct { miInteger index; miTag type; miTag filename; } indexed_framebuffer; /* Parameter struct for shader function: */ struct make_indexed_framebuffers { miTag option_block_name; int i_fb; int n_fb; indexed_framebuffer fb[1]; }; /* Struct to store the arguments resulting from evaluating shader parameters: */ typedef struct { int index; char* type; char* filename; char* ext; char* name; } fb_args; /* Evaluate the parameters for the arguments required to define framebuffers: */ char* tag_to_string(miTag tag, char *default_value) { char *result = default_value; if (tag != 0) { result = (char*)mi_db_access(tag); mi_db_unpin(tag); } return result; } char* get_extension(char *filename) { char* extension = NULL; if (filename) { extension = strrchr(filename, '.'); if (extension) extension++; /* String after "." */ } return extension; } /* Get the set of arguments by evaluating parameters: */ void get_indexed_framebuffer_args( fb_args args[], int count, miState *state, struct make_indexed_framebuffers *params) { int i_fb = *mi_eval_integer(¶ms->i_fb), i; mi_info("Making %i user framebuffers:", count); for (i = 0; i < count; ++i) { char name[16]; indexed_framebuffer fb = params->fb[i + i_fb]; args[i].index = *mi_eval_integer(&fb.index); args[i].type = tag_to_string(*mi_eval_tag(&fb.type), NULL); args[i].filename = tag_to_string(*mi_eval_tag(&fb.filename), NULL); args[i].ext = get_extension(args[i].filename); sprintf(name, "fb%d", args[i].index); args[i].name = mi_mem_strdup(name); mi_progress(" Buffer %d: filename '%s', type '%s', ext '%s', name '%s'", args[i].index, args[i].filename, args[i].type, args[i].ext, args[i].name); } } /* Shader functions: */ DLLEXPORT int make_indexed_framebuffers_version(void) { return 1; } DLLEXPORT miBoolean make_indexed_framebuffers ( miTag *result, miState *state, struct make_indexed_framebuffers *params) { char* option_block_name = tag_to_string(*mi_eval_tag(¶ms->option_block_name), "opt"); miOptions* options = (miOptions*)(state->options); int count = *mi_eval_integer(¶ms->n_fb), i; fb_args* args = (fb_args*)mi_mem_allocate(count * sizeof(fb_args)); get_indexed_framebuffer_args(args, count, state, params); mi_api_options_begin(mi_mem_strdup(option_block_name)); for (i = 0; i < count; ++i) mi_api_framebuffer( options, args[i].index, mi_mem_strdup(args[i].type)); mi_api_options_end(); for (i = 0; i < count; ++i) { /* A framebuffer might not be output to file; check for a filename: */ if (args[i].filename && strlen(args[i].filename) > 0) { mi_api_framebuffer_add( state->camera->buffertag, mi_mem_strdup(args[i].name), mi_mem_strdup(args[i].ext), 0, mi_mem_strdup(args[i].filename)); } } mi_mem_release(args); return miTRUE; }