static void codegen_declare_tmps(DynStr *ds, ListBase *nodes) { GPUNode *node; GPUInput *input; GPUOutput *output; for (node=nodes->first; node; node=node->next) { /* load pixels from textures */ for (input=node->inputs.first; input; input=input->next) { if (input->source == GPU_SOURCE_TEX_PIXEL) { if (codegen_input_has_texture(input) && input->definetex) { BLI_dynstr_appendf(ds, "\tvec4 tex%d = texture2D(", input->texid); BLI_dynstr_appendf(ds, "samp%d, gl_TexCoord[%d].st);\n", input->texid, input->texid); } } } /* declare temporary variables for node output storage */ for (output=node->outputs.first; output; output=output->next) BLI_dynstr_appendf(ds, "\t%s tmp%d;\n", GPU_DATATYPE_STR[output->type], output->id); } BLI_dynstr_append(ds, "\n"); }
static void codegen_print_datatype(DynStr *ds, int type, float *data) { int i; BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]); for (i=0; i<type; i++) { BLI_dynstr_appendf(ds, "%f", data[i]); if (i == type-1) BLI_dynstr_append(ds, ")"); else BLI_dynstr_append(ds, ", "); } }
static char *bmp_slots_as_args(const BMOSlotType slot_types[BMO_OP_MAX_SLOTS], const bool is_out) { DynStr *dyn_str = BLI_dynstr_new(); char *ret; int i = 0; while (*slot_types[i].name) { /* cut off '.out' by using a string size arg */ const int name_len = is_out ? (strchr(slot_types[i].name, '.') - slot_types[i].name) : sizeof(slot_types[i].name); const char *value = "<Unknown>"; switch (slot_types[i].type) { case BMO_OP_SLOT_BOOL: value = "False"; break; case BMO_OP_SLOT_INT: value = "0"; break; case BMO_OP_SLOT_FLT: value = "0.0"; break; case BMO_OP_SLOT_PTR: value = "None"; break; case BMO_OP_SLOT_MAT: value = "Matrix()"; break; case BMO_OP_SLOT_VEC: value = "Vector()"; break; case BMO_OP_SLOT_ELEMENT_BUF: value = (slot_types[i].subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) ? "None" : "[]"; break; case BMO_OP_SLOT_MAPPING: value = "{}"; break; } BLI_dynstr_appendf(dyn_str, i ? ", %.*s=%s" : "%.*s=%s", name_len, slot_types[i].name, value); i++; } ret = BLI_dynstr_get_cstring(dyn_str); BLI_dynstr_free(dyn_str); return ret; }
static char *gpu_generate_function_prototyps(GHash *hash) { DynStr *ds = BLI_dynstr_new(); GHashIterator *ghi; GPUFunction *function; char *name, *prototypes; int a; /* automatically generate function prototypes to add to the top of the * generated code, to avoid have to add the actual code & recompile all */ ghi = BLI_ghashIterator_new(hash); for (; !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) { name = BLI_ghashIterator_getValue(ghi); function = BLI_ghashIterator_getValue(ghi); BLI_dynstr_appendf(ds, "void %s(", name); for (a = 0; a < function->totparam; a++) { if (function->paramqual[a] == FUNCTION_QUAL_OUT) BLI_dynstr_append(ds, "out "); else if (function->paramqual[a] == FUNCTION_QUAL_INOUT) BLI_dynstr_append(ds, "inout "); if (function->paramtype[a] == GPU_TEX2D) BLI_dynstr_append(ds, "sampler2D"); else if (function->paramtype[a] == GPU_SHADOW2D) BLI_dynstr_append(ds, "sampler2DShadow"); else BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]); # if 0 BLI_dynstr_appendf(ds, " param%d", a); # endif if (a != function->totparam-1) BLI_dynstr_append(ds, ", "); } BLI_dynstr_append(ds, ");\n"); } BLI_dynstr_append(ds, "\n"); prototypes = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); return prototypes; }
static char *code_generate_vertex(ListBase *nodes) { DynStr *ds = BLI_dynstr_new(); GPUNode *node; GPUInput *input; char *code; for (node=nodes->first; node; node=node->next) { for (input=node->inputs.first; input; input=input->next) { if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { BLI_dynstr_appendf(ds, "attribute %s att%d;\n", GPU_DATATYPE_STR[input->type], input->attribid); BLI_dynstr_appendf(ds, "varying %s var%d;\n", GPU_DATATYPE_STR[input->type], input->attribid); } } } BLI_dynstr_append(ds, "\n"); BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl); for (node=nodes->first; node; node=node->next) for (input=node->inputs.first; input; input=input->next) if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { if(input->attribtype == CD_TANGENT) /* silly exception */ { BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize((gl_ModelViewMatrix * vec4(att%d.xyz, 0)).xyz);\n", input->attribid, input->attribid); BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid); } else BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid); } BLI_dynstr_append(ds, "}\n\n"); code = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); //if(G.f & G_DEBUG) printf("%s\n", code); return code; }
static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput) { GPUNode *node; GPUInput *input; GPUOutput *output; for (node = nodes->first; node; node = node->next) { BLI_dynstr_appendf(ds, "\t%s(", node->name); for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_TEX) { BLI_dynstr_appendf(ds, "samp%d", input->texid); if (input->link) BLI_dynstr_appendf(ds, ", gl_TexCoord[%d].st", input->texid); } else if (input->source == GPU_SOURCE_TEX_PIXEL) { codegen_convert_datatype(ds, input->link->output->type, input->type, "tmp", input->link->output->id); } else if (input->source == GPU_SOURCE_BUILTIN) { if (input->builtin == GPU_VIEW_NORMAL) BLI_dynstr_append(ds, "facingnormal"); else BLI_dynstr_append(ds, GPU_builtin_name(input->builtin)); } else if (input->source == GPU_SOURCE_VEC_UNIFORM) { if (input->dynamicvec) BLI_dynstr_appendf(ds, "unf%d", input->id); else BLI_dynstr_appendf(ds, "cons%d", input->id); } else if (input->source == GPU_SOURCE_ATTRIB) { BLI_dynstr_appendf(ds, "var%d", input->attribid); } else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) { if (input->oglbuiltin == GPU_MATCAP_NORMAL) BLI_dynstr_append(ds, "gl_SecondaryColor"); else if (input->oglbuiltin == GPU_COLOR) BLI_dynstr_append(ds, "gl_Color"); } BLI_dynstr_append(ds, ", "); } for (output = node->outputs.first; output; output = output->next) { BLI_dynstr_appendf(ds, "tmp%d", output->id); if (output->next) BLI_dynstr_append(ds, ", "); } BLI_dynstr_append(ds, ");\n"); } BLI_dynstr_append(ds, "\n\tgl_FragColor = "); codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id); BLI_dynstr_append(ds, ";\n"); }
static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes) { GPUNode *node; GPUInput *input; const char *name; int builtins = 0; /* print uniforms */ for (node=nodes->first; node; node=node->next) { for (input=node->inputs.first; input; input=input->next) { if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) { /* create exactly one sampler for each texture */ if (codegen_input_has_texture(input) && input->bindtex) BLI_dynstr_appendf(ds, "uniform %s samp%d;\n", (input->textype == GPU_TEX2D) ? "sampler2D" : "sampler2DShadow", input->texid); } else if (input->source == GPU_SOURCE_BUILTIN) { /* only define each builting uniform/varying once */ if (!(builtins & input->builtin)) { builtins |= input->builtin; name = GPU_builtin_name(input->builtin); if (gpu_str_prefix(name, "unf")) { BLI_dynstr_appendf(ds, "uniform %s %s;\n", GPU_DATATYPE_STR[input->type], name); } else { BLI_dynstr_appendf(ds, "varying %s %s;\n", GPU_DATATYPE_STR[input->type], name); } } } else if (input->source == GPU_SOURCE_VEC_UNIFORM) { if (input->dynamicvec) { /* only create uniforms for dynamic vectors */ BLI_dynstr_appendf(ds, "uniform %s unf%d;\n", GPU_DATATYPE_STR[input->type], input->id); } else { /* for others use const so the compiler can do folding */ BLI_dynstr_appendf(ds, "const %s cons%d = ", GPU_DATATYPE_STR[input->type], input->id); codegen_print_datatype(ds, input->type, input->vec); BLI_dynstr_append(ds, ";\n"); } } else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { BLI_dynstr_appendf(ds, "varying %s var%d;\n", GPU_DATATYPE_STR[input->type], input->attribid); } } } BLI_dynstr_append(ds, "\n"); return builtins; }
static PyObject *Euler_str(EulerObject *self) { DynStr *ds; if (BaseMath_ReadCallback(self) == -1) return NULL; ds = BLI_dynstr_new(); BLI_dynstr_appendf(ds, "<Euler (x=%.4f, y=%.4f, z=%.4f), order='%s'>", self->eul[0], self->eul[1], self->eul[2], euler_order_str(self)); return mathutils_dynstr_to_py(ds); /* frees ds */ }
static PyObject *Quaternion_str(QuaternionObject *self) { DynStr *ds; if (BaseMath_ReadCallback(self) == -1) return NULL; ds = BLI_dynstr_new(); BLI_dynstr_appendf(ds, "<Quaternion (w=%.4f, x=%.4f, y=%.4f, z=%.4f)>", self->quat[0], self->quat[1], self->quat[2], self->quat[3]); return mathutils_dynstr_to_py(ds); /* frees ds */ }
static PyObject *Color_str(ColorObject *self) { DynStr *ds; if (BaseMath_ReadCallback(self) == -1) return NULL; ds = BLI_dynstr_new(); BLI_dynstr_appendf(ds, "<Color (r=%.4f, g=%.4f, b=%.4f)>", self->col[0], self->col[1], self->col[2]); return mathutils_dynstr_to_py(ds); /* frees ds */ }
char *BPy_enum_as_string(EnumPropertyItem *item) { DynStr *dynstr = BLI_dynstr_new(); EnumPropertyItem *e; char *cstring; for (e = item; item->identifier; item++) { if (item->identifier[0]) BLI_dynstr_appendf(dynstr, (e == item) ? "'%s'" : ", '%s'", item->identifier); } cstring = BLI_dynstr_get_cstring(dynstr); BLI_dynstr_free(dynstr); return cstring; }
char *BKE_reports_string(ReportList *reports, ReportType level) { Report *report; DynStr *ds; char *cstring; if (!reports || !reports->list.first) return NULL; ds= BLI_dynstr_new(); for (report=reports->list.first; report; report=report->next) if (report->type >= level) BLI_dynstr_appendf(ds, "%s: %s\n", report->typestr, report->message); if (BLI_dynstr_get_len(ds)) cstring= BLI_dynstr_get_cstring(ds); else cstring= NULL; BLI_dynstr_free(ds); return cstring; }
static char *code_generate_fragment(ListBase *nodes, GPUOutput *output) { DynStr *ds = BLI_dynstr_new(); char *code; int builtins; #if 0 BLI_dynstr_append(ds, FUNCTION_PROTOTYPES); #endif codegen_set_unique_ids(nodes); builtins = codegen_print_uniforms_functions(ds, nodes); #if 0 if (G.debug & G_DEBUG) BLI_dynstr_appendf(ds, "/* %s */\n", name); #endif BLI_dynstr_append(ds, "void main(void)\n"); BLI_dynstr_append(ds, "{\n"); if (builtins & GPU_VIEW_NORMAL) BLI_dynstr_append(ds, "\tvec3 facingnormal = (gl_FrontFacing)? varnormal: -varnormal;\n"); codegen_declare_tmps(ds, nodes); codegen_call_functions(ds, nodes, output); BLI_dynstr_append(ds, "}\n"); /* create shader */ code = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); #if 0 if (G.debug & G_DEBUG) printf("%s\n", code); #endif return code; }
static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *tmp, int id) { char name[1024]; BLI_snprintf(name, sizeof(name), "%s%d", tmp, id); if (from == to) { BLI_dynstr_append(ds, name); } else if (to == GPU_FLOAT) { if (from == GPU_VEC4) BLI_dynstr_appendf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name); else if (from == GPU_VEC3) BLI_dynstr_appendf(ds, "dot(%s, vec3(0.33))", name); else if (from == GPU_VEC2) BLI_dynstr_appendf(ds, "%s.r", name); } else if (to == GPU_VEC2) { if (from == GPU_VEC4) BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name); else if (from == GPU_VEC3) BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name); else if (from == GPU_FLOAT) BLI_dynstr_appendf(ds, "vec2(%s, 1.0)", name); } else if (to == GPU_VEC3) { if (from == GPU_VEC4) BLI_dynstr_appendf(ds, "%s.rgb", name); else if (from == GPU_VEC2) BLI_dynstr_appendf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name); else if (from == GPU_FLOAT) BLI_dynstr_appendf(ds, "vec3(%s, %s, %s)", name, name, name); } else { if (from == GPU_VEC3) BLI_dynstr_appendf(ds, "vec4(%s, 1.0)", name); else if (from == GPU_VEC2) BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name); else if (from == GPU_FLOAT) BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name); } }
static char *code_generate_vertex(ListBase *nodes, const GPUMatType type) { DynStr *ds = BLI_dynstr_new(); GPUNode *node; GPUInput *input; char *code; char *vertcode; for (node = nodes->first; node; node = node->next) { for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { BLI_dynstr_appendf(ds, "attribute %s att%d;\n", GPU_DATATYPE_STR[input->type], input->attribid); BLI_dynstr_appendf(ds, "varying %s var%d;\n", GPU_DATATYPE_STR[input->type], input->attribid); } } } BLI_dynstr_append(ds, "\n"); switch (type) { case GPU_MATERIAL_TYPE_MESH: vertcode = datatoc_gpu_shader_vertex_glsl; break; case GPU_MATERIAL_TYPE_WORLD: vertcode = datatoc_gpu_shader_vertex_world_glsl; break; default: fprintf(stderr, "invalid material type, set one after GPU_material_construct_begin\n"); break; } BLI_dynstr_append(ds, vertcode); for (node = nodes->first; node; node = node->next) for (input = node->inputs.first; input; input = input->next) if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { if (input->attribtype == CD_TANGENT) { /* silly exception */ BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n", input->attribid, input->attribid); BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid); } else BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid); } /* unfortunately special handling is needed here because we abuse gl_Color/gl_SecondaryColor flat shading */ else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) { if (input->oglbuiltin == GPU_MATCAP_NORMAL) { /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors * between shader stages and we want the full range of the normal */ BLI_dynstr_appendf(ds, "\tvec3 matcapcol = vec3(0.5, 0.5, 0.5) * varnormal + vec3(0.5, 0.5, 0.5);\n"); BLI_dynstr_appendf(ds, "\tgl_FrontSecondaryColor = vec4(matcapcol, 1.0);\n"); } else if (input->oglbuiltin == GPU_COLOR) { BLI_dynstr_appendf(ds, "\tgl_FrontColor = gl_Color;\n"); } } BLI_dynstr_append(ds, "}\n\n"); code = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); #if 0 if (G.debug & G_DEBUG) printf("%s\n", code); #endif return code; }