extern "C" DLLEXPORT miBoolean mib_texture_filter_lookup( miColor *result, miState *state, struct mib_texture_filter_lookup *paras) { miTag tex = *mi_eval_tag(¶s->tex); miVector *coord; miUint space; miTag remap; miVector p[3], t[3]; miMatrix ST; miTexfilter ell_opt; miScalar disc_r; if (!tex) { result->r = result->g = result->b = result->a = 0; return(miFALSE); } coord = mi_eval_vector(¶s->coord); space = *mi_eval_integer(¶s->space); disc_r = *mi_eval_scalar(¶s->disc_r); if (disc_r <= 0) disc_r = DISC_R; if (state->reflection_level == 0 && mi_texture_filter_project(p, t, state, disc_r, space) && (remap = *mi_eval_tag(¶s->remap))) { mi_call_shader_x((miColor*)&t[0], miSHADER_TEXTURE, state, remap, &t[0]); mi_call_shader_x((miColor*)&t[1], miSHADER_TEXTURE, state, remap, &t[1]); mi_call_shader_x((miColor*)&t[2], miSHADER_TEXTURE, state, remap, &t[2]); if (mi_texture_filter_transform(ST, p, t)) { ell_opt.eccmax = *mi_eval_scalar(¶s->eccmax); ell_opt.max_minor = *mi_eval_scalar(¶s->maxminor); ell_opt.bilinear = *mi_eval_boolean(¶s->bilinear); ell_opt.circle_radius = CIRCLE_R; /* * when no bump-mapping is used, coord and ST[..] * are identical. for bump mapping, the projection * matrix is calculated for the current raster * position, the ellipse is translated to the * bump position */ ST[2*4+0] = coord->x; ST[2*4+1] = coord->y; if (mi_lookup_filter_color_texture(result, state, tex, &ell_opt, ST)) return(miTRUE); } } /* fallback to standard pyramid or nonfiltered texture lookup */ return(mi_lookup_color_texture(result, state, tex, coord)); }
extern "C" DLLEXPORT miBoolean mib_texture_lookup( miColor *result, miState *state, struct mib_texture_lookup *paras) { miTag tex = *mi_eval_tag(¶s->tex); miVector *coord = mi_eval_vector(¶s->coord); if (tex && coord->x >= 0 && coord->x < 1 && coord->y >= 0 && coord->y < 1 && mi_lookup_color_texture(result, state, tex, coord)) return(miTRUE); result->r = result->g = result->b = result->a = 0; return(miFALSE); }
extern "C" DLLEXPORT miBoolean mib_lens_stencil( miColor* result, miState* state, mibStencil_t* paras) { miScalar f = *mi_eval_scalar(¶s->floor); miScalar c = *mi_eval_scalar(¶s->ceiling); miColor fc = *mi_eval_color(¶s->floor_color); miColor cc = *mi_eval_color(¶s->ceil_color); miTag st = *mi_eval_tag(¶s->stencil); miScalar s; miVector coord; /* handle default parameter values */ if (c == 0.0f) { c = 1.0f; } if (!st || f >= c) { return mi_trace_eye(result, state, &state->org, &state->dir); } coord.x = state->raster_x / state->camera->x_resolution; coord.y = state->raster_y / state->camera->y_resolution; coord.z = 0.0f; mi_lookup_scalar_texture(&s, state, st, &coord); s = (s-f)/(c-f); if (s < 0.0f) { *result = fc; } else if ( s > 1.0f) { *result = cc; } else { miColor col = { 0.0, 0.0, 0.0, 1.0}; miScalar sn = 1.0f - s; (void) mi_trace_eye(&col, state, &state->org, &state->dir); result->r = s * col.r + sn * fc.r; result->g = s * col.g + sn * fc.g; result->b = s * col.b + sn * fc.b; result->a = col.a; } return miTRUE; }
miBoolean contour_shader_widthfromlight( miContour_endpoint *result, miStdInfo *info_near, miStdInfo *info_far, miState *state, Light_Parameters *paras) { miVector orgp; /* light source origin */ miVector dirp; /* light source direction */ miVector dir; double d; miScalar min_width; miScalar max_width; /* Contour color given by a parameter */ result->color = *mi_eval_color(¶s->color); /* Get light origin or direction */ mi_light_info(*mi_eval_tag(¶s->light), &orgp, &dirp, 0); /* Now orgp or dirp is different from the null vector */ /* Compute direction from light to point */ if (mi_vector_dot(&orgp, &orgp) > miEPS) { /* point light source */ mi_vector_sub(&dir, &info_near->point, &orgp); } else { /* directional light source */ miASSERT(mi_vector_dot(&dirp, &dirp) > miEPS); dir = dirp; } mi_vector_normalize(&dir); /* The contour gets wider the more the normal is pointing in the same direction as the light source */ d = mi_vector_dot(&dir, &info_near->normal); min_width = *mi_eval_scalar(¶s->min_width); max_width = *mi_eval_scalar(¶s->max_width); result->width = min_width + 0.5 * (max_width - min_width) * (d+1.0); miASSERT(min_width <= result->width && result->width <= max_width); return(miTRUE); }
extern "C" DLLEXPORT miBoolean mib_texture_lookup2( miColor *result, miState *state, struct mib_texture_lookup2 *paras) { miTag tex = *mi_eval_tag(¶s->tex); miVector coord; miScalar factor = *mi_eval_scalar(¶s->factor); if (tex ) { coord.x = state->tex_list[0].x * factor; coord.y = state->tex_list[0].y * factor; mi_lookup_color_texture(result, state, tex, &coord); return(miTRUE); } result->r = result->g = result->b = result->a = 0; return(miFALSE); }
extern "C" DLLEXPORT miBoolean mib_ray_marcher( miColor *result, miState *state, struct mrm *p) { struct mrm pe; miScalar scale; result->r = result->g = result->b = result->a = 0.0; /* * copy all parameters to a static structure to * avoid all the mi_eval_* calls in the code */ pe.s = *mi_eval_tag(&p->s); pe.distance = *mi_eval_scalar(&p->distance); pe.num = *mi_eval_integer(&p->num); pe.subdiv = *mi_eval_integer(&p->subdiv); pe.contrast = *mi_eval_color(&p->contrast); if (pe.num == 0.0) if (pe.distance > 0.0) pe.num = state->dist / pe.distance; else pe.num = 4; /* default #samples */ if (pe.num < 2) pe.num = 2; /* go! */ raymarch(result, state, &pe); /* normalize result */ scale = 1.0 / (miScalar)pe.num; result->r *= scale; result->g *= scale; result->b *= scale; result->a *= scale; return(miTRUE); }
extern "C" DLLEXPORT miBoolean mrParticleGeoShader( miTag *result, miState *state, mrParticleGeoShader_paras *paras) { mi_info("mrParticleGeoShader: Version %s", VERSION); int geometryType = *mi_eval_integer(¶s->geometryType); miScalar minPixelSize = *mi_eval_scalar(¶s->minPixelSize); miScalar maxPixelSize = *mi_eval_scalar(¶s->maxPixelSize); int i_m = *mi_eval_integer(¶s->i_particleFiles); int n_m = *mi_eval_integer(¶s->n_particleFiles); miTag *particleFiles = mi_eval_tag(paras->particleFiles) + i_m; for(int i = 0; i < n_m; i++) { if (particleFiles[i]) { std::string fileName = tag_to_string(particleFiles[i]); std::string correctedFileName = getCorrectFileName(state, paras, fileName); mi_info("reading cacheFile %s", correctedFileName.c_str()); PartioContainer pc(correctedFileName); if( geometryType == 0) { miTag particleTag = createMeshParticles(state, paras, pc); if( particleTag != miNULLTAG) miBoolean done = mi_geoshader_add_result( result, particleTag); }else{ miTag particleTag = createNativeParticles(state, paras, pc); if( particleTag != miNULLTAG) miBoolean done = mi_geoshader_add_result( result, particleTag); } } } return miTRUE; }
miBoolean contour_shader_combi( miContour_endpoint *result, miStdInfo *info_near, miStdInfo *info_far, miState *state, Combi_Parameters *paras) { miScalar depth = info_near->point.z; double near_z, far_z, w_near, w_far; miVector orgp; /* light source origin */ miVector dirp; /* light source direction */ miVector dir; double d; double factor; miTag light; /* Ensure that near_z and far_z are negative as they should be */ near_z = -fabs(*mi_eval_scalar(¶s->near_z)); far_z = -fabs(*mi_eval_scalar(¶s->far_z)); if (depth > near_z) { /* contour is closer than near_z */ result->color = *mi_eval_color(¶s->near_color); result->width = *mi_eval_scalar(¶s->near_width); } else if (depth < far_z) { /* contour is more distant than far_z*/ result->color = *mi_eval_color(¶s->far_color); result->width = *mi_eval_scalar(¶s->far_width); } else { /* contour is betwn near_z and far_z */ miColor near_color = *mi_eval_color(¶s->near_color); miColor far_color = *mi_eval_color(¶s->far_color); /* Weights w_near and w_far depend on depth */ w_near = (depth - far_z) / (near_z - far_z); miASSERT(0.0 <= w_near && w_near <= 1.0); w_far = 1.0 - w_near; /* Mix of near_color and far_color according to weights */ result->color.r = w_near * near_color.r + w_far * far_color.r; result->color.g = w_near * near_color.g + w_far * far_color.g; result->color.b = w_near * near_color.b + w_far * far_color.b; result->color.a = w_near * near_color.a + w_far * far_color.a; /* Width depending on weights */ result->width = w_near * *mi_eval_scalar(¶s->near_width) + w_far * *mi_eval_scalar(¶s->far_width); } /* Width decreases by factor for each refraction_level */ factor = *mi_eval_scalar(¶s->factor); if (factor > miEPS) result->width *= pow(factor, (double)info_near->level - 1.0); light = *mi_eval_tag(¶s->light); if (light) { miScalar light_min_factor = *mi_eval_scalar(¶s->light_min_factor); /* Get light origin or direction */ mi_light_info(light, &orgp, &dirp, 0); /* Now orgp or dirp is different from the null vector */ /* Compute direction from light to point */ if (mi_vector_dot(&orgp, &orgp) > miEPS) /* point light */ mi_vector_sub(&dir, &info_near->point, &orgp); else { /* directional light source */ miASSERT(mi_vector_dot(&dirp, &dirp) > miEPS); dir = dirp; } mi_vector_normalize(&dir); /* The contour gets wider the more the normal is pointing in the same direction as the light source */ d = mi_vector_dot(&dir, &info_near->normal); result->width *= 0.5 * (d + 1.0) * (1.0 - light_min_factor) + light_min_factor; } miASSERT(result->width <= *mi_eval_scalar(¶s->near_width)); return(miTRUE); }
extern "C" DLLEXPORT miBoolean mib_illum_lambert( miColor *result, miState *state, struct mib_illum_lambert *paras) { miColor *ambi, *diff; miTag *light; /* tag of light instance */ int n_l; /* number of light sources */ int i_l; /* offset of light sources */ int m; /* light mode: 0=all, 1=incl, 2=excl */ int samples; /* # of samples taken */ miColor color; /* color from light source */ miColor sum; /* summed sample colors */ miScalar dot_nl; /* dot prod of normal and dir*/ /* check for illegal calls */ if (state->type == miRAY_SHADOW || state->type == miRAY_DISPLACE ) { return(miFALSE); } ambi = mi_eval_color(¶s->ambient); diff = mi_eval_color(¶s->diffuse); m = *mi_eval_integer(¶s->mode); *result = *mi_eval_color(¶s->ambience); /* ambient term */ result->r *= ambi->r; result->g *= ambi->g; result->b *= ambi->b; n_l = *mi_eval_integer(¶s->n_light); i_l = *mi_eval_integer(¶s->i_light); light = mi_eval_tag(paras->light) + i_l; if (m == 1) /* modify light list (inclusive mode) */ mi_inclusive_lightlist(&n_l, &light, state); else if (m == 2) /* modify light list (exclusive mode) */ mi_exclusive_lightlist(&n_l, &light, state); else if (m == 4) { n_l = 0; light = 0; } /* Loop over all light sources */ if (m==4 || n_l) { for (mi::shader::LightIterator iter(state, light, n_l); !iter.at_end(); ++iter) { sum.r = sum.g = sum.b = 0; while (iter->sample()) { dot_nl = iter->get_dot_nl(); iter->get_contribution(&color); sum.r += dot_nl * diff->r * color.r; sum.g += dot_nl * diff->g * color.g; sum.b += dot_nl * diff->b * color.b; } samples = iter->get_number_of_samples(); if (samples) { result->r += sum.r / samples; result->g += sum.g / samples; result->b += sum.b / samples; } } } /* add contribution from indirect illumination (caustics) */ mi_compute_irradiance(&color, state); result->r += color.r * diff->r; result->g += color.g * diff->g; result->b += color.b * diff->b; result->a = 1; return(miTRUE); }
extern "C" DLLEXPORT miBoolean mib_illum_cooktorr( miColor *result, miState *state, struct mib_illum_cooktorr *paras) { miColor *ambi, *diff, *spec; miScalar roughness; /* average microfacet slope */ miColor *ior; /* index of refraction */ miTag *light; /* tag of light instance */ int n_l; /* number of light sources */ int i_l; /* offset of light sources */ int mode; /* light mode: 0=all, 1=incl, 2=excl */ int samples; /* # of samples taken */ miColor color; /* color from light source */ miColor sum; /* summed sample colors */ miVector dir; /* direction towards light */ miScalar dot_nl; /* dot prod of normal and dir */ miColor refl; /* specular reflection color */ /* check for illegal calls */ if (state->type == miRAY_SHADOW || state->type == miRAY_DISPLACE ) { return(miFALSE); } ambi = mi_eval_color(¶s->ambient); diff = mi_eval_color(¶s->diffuse); spec = mi_eval_color(¶s->specular); roughness = *mi_eval_scalar(¶s->roughness); ior = mi_eval_color(¶s->ior); *result = *mi_eval_color(¶s->ambience); /* ambient term */ result->r *= ambi->r; result->g *= ambi->g; result->b *= ambi->b; mode = *mi_eval_integer(¶s->mode); n_l = *mi_eval_integer(¶s->n_light); i_l = *mi_eval_integer(¶s->i_light); light = mi_eval_tag(paras->light) + i_l; if (mode == 1) /* modify light list (inclusive mode) */ mi_inclusive_lightlist(&n_l, &light, state); else if (mode == 2) /* modify light list (exclusive mode) */ mi_exclusive_lightlist(&n_l, &light, state); else if (mode == 4) { n_l = 0; light = 0; } /* Loop over all light sources */ if (mode == 4 || n_l) { for (mi::shader::LightIterator iter(state, light, n_l); !iter.at_end(); ++iter) { sum.r = sum.g = sum.b = 0; samples = 0; while (iter->sample()) { iter->get_contribution(&color); dot_nl = iter->get_dot_nl(); /* Diffuse reflection: Lambert's cosine law */ sum.r += dot_nl * diff->r * color.r; sum.g += dot_nl * diff->g * color.g; sum.b += dot_nl * diff->b * color.b; /* Specular reflection: Cook-Torrance reflection */ dir = iter->get_direction(); if (mi_cooktorr_specular(&refl, &state->dir, &dir, &state->normal, roughness, ior)) { sum.r += refl.r * spec->r * color.r; sum.g += refl.g * spec->g * color.g; sum.b += refl.b * spec->b * color.b; } } samples = iter->get_number_of_samples(); if (samples) { result->r += sum.r / samples; result->g += sum.g / samples; result->b += sum.b / samples; } } } /* add contribution from indirect illumination (caustics) */ mi_compute_irradiance(&color, state); result->r += color.r * diff->r; result->g += color.g * diff->g; result->b += color.b * diff->b; result->a = 1; return(miTRUE); }
extern "C" DLLEXPORT miBoolean mib_bent_normal_env( miColor *result, miState *state, struct mib_bent_normal_env_p *paras) { miTag original_env = state->environment; miTag environment = *mi_eval_tag(¶s->environment); miColor normal = *mi_eval_color(¶s->bent_normals); miColor occlus = *mi_eval_color(¶s->occlusion); miScalar strength = *mi_eval_scalar(¶s->strength); miColor color; /* Work color */ miVector bent; /* Bent normals */ miVector bent_i; /* Bent normals in internal space */ miUint samples; /* # of samples */ /* Displace or light - makes no sense */ if (state->type == miRAY_DISPLACE || state->type == miRAY_LIGHT) return miFALSE; if (strength == 0.0) { result->r = result->g = result->b = 0.0; result->a = 1.0; return miTRUE; } color.r = color.b = color.g = 0.0; /* Does occlusion live in "alpha" component of bn data? */ if (*mi_eval_boolean(¶s->occlusion_in_alpha)) strength *= normal.a; bent.x = (normal.r * 2.0) - 1.0; bent.y = (normal.g * 2.0) - 1.0; bent.z = (normal.b * 2.0) - 1.0; mi_vector_normalize(&bent); /* The different coordinate spaces */ switch(*mi_eval_integer(¶s->coordinate_space)) { case 0: /* No change */ bent_i = bent; break; case 1: /* By matrix */ mi_vector_transform(&bent_i, &bent, mi_eval_transform(¶s->matrix)); break; case 2: /* World */ mi_normal_from_world(state, &bent_i, &bent); break; case 3: /* Camera */ mi_normal_from_camera(state, &bent_i, &bent); break; case 4: /* Object */ mi_normal_from_object(state, &bent_i, &bent); break; } samples = *mi_eval_integer(¶s->env_samples); /* Temporarily override the environment */ if (environment) state->environment = environment; if (samples <= 1) { /* Single sampling */ mi_trace_environment(&color, state, &bent_i); } else { /* Multisampling */ double sample[3]; int counter = 0; miScalar spread = *mi_eval_scalar(¶s->samples_spread); miColor work_color; /* Clear color */ color.r = color.g = color.b = 0.0; while (mi_sample(sample, &counter, state, 3, &samples)) { miVector trace_dir; trace_dir.x = bent_i.x + (sample[0] - 0.5) * spread; trace_dir.y = bent_i.y + (sample[1] - 0.5) * spread; trace_dir.z = bent_i.z + (sample[2] - 0.5) * spread; mi_vector_normalize(&trace_dir); mi_trace_environment(&work_color, state, &trace_dir); color.r += work_color.r; color.g += work_color.g; color.b += work_color.b; } color.r /= samples; color.g /= samples; color.b /= samples; } /* Reset original environment */ state->environment = original_env; result->r = color.r * occlus.r * strength; result->g = color.g * occlus.g * strength; result->b = color.b * occlus.b * strength; result->a = 1.0; return miTRUE; }
miTag createNativeParticles(miState *state, mrParticleGeoShader_paras *paras, PartioContainer& pc) { miBoolean useAllAttributes = *mi_eval_boolean(¶s->useAllAttributes); int i_a = *mi_eval_integer(¶s->i_attributeNames); int n_a = *mi_eval_integer(¶s->n_attributeNames); miTag *attributeNames = mi_eval_tag(paras->attributeNames) + i_a; if( !pc.good()) { mi_info("createNativeParticles: Invalid patioContainer"); return miNULLTAG; } Partio::ParticleAttribute posAttr; if(!pc.assertAttribute("position", posAttr)) { mi_info("createNativeParticles: partioContainer: no position."); return miNULLTAG; } Partio::ParticleAttribute idAttr; bool hasId = true; if(!pc.assertAttribute("id", idAttr)) hasId = false; Partio::ParticleAttribute radiusPPAttr; bool hasRadiusPP = true; if(!pc.assertAttribute("radiusPP", radiusPPAttr)) hasRadiusPP = false; Partio::ParticleAttribute radiusRGBPPAttr; bool hasRgbPP = true; if(!pc.assertAttribute("rgbPP", radiusRGBPPAttr)) hasRgbPP = false; mi_info("Creating native particles for cache file: %s", pc.cacheFileName.c_str()); // declare the map as a 3-dimensional map mi_api_map_decl_dim ( 3 ); // the 'mi_api_map_field_decl' function takes four arguments: // // miParam_type type: basic type of the field (miTYPE_SCALAR or miTYPE_INTEGER) // char *name : field name // int dimension : dimension of the field, 0 for single values, > 0 for arrays // miBoolean global : miTRUE if it's a global field, miFALSE otherwise // add the "extension" field as a single float miParameter *extension_field = mi_api_map_field_decl ( miTYPE_SCALAR , mi_mem_strdup("extension") , 0 , miFALSE ); // add the "color" field as an array of 1 color miParameter *color_field = mi_api_map_field_decl ( miTYPE_SCALAR , mi_mem_strdup("color") , 3 , miFALSE ); // append the color to the extension for the declaration // (this also frees the 'color_field' miParameter) miParameter *fields_list = mi_api_map_field_append ( extension_field , color_field ); // create a declaration called "particles" with the given fields list // (this also frees the 'fields_list' miParameter) miMap_decl *decl = mi_api_map_decl_begin ( mi_mem_strdup("particles") , fields_list ); // ends the declaration mi_api_map_decl_end (); // Then you begin the object definition, by calling 'mi_api_object_begin' and possibly setting the object flags as needed, then you begin the definition of the particle object as a set of spheres: miObject *obj = mi_api_object_begin(mi_mem_strdup("TestParticleObject")); obj->visible = miTRUE; // begin the definition of the particle object as spheres mi_api_map_obj_type ( mi_mem_strdup("spheres") ); // the 'mi_api_map_obj_field' function takes 2 arguments: // // char *field_name : name of the field to map ("radius" in this case) // char *mapped_name : name of the mapped field ("extension" in this case) // maps the "radius" field to the "extension" field of this map mi_api_map_obj_field( mi_mem_strdup("radius") , mi_mem_strdup("extension") ); // begins the definition of the map, taking "particles" as the declaration name mi_api_map_begin ( mi_mem_strdup("particles") ); int num_elements = pc.data->numParticles(); for ( int i = 0 ; i < num_elements ; ++i ) { float pos[3]; pc.getPosition(i, pos); // define the position of this element mi_api_map_value ( miTYPE_SCALAR , &pos[0] ); mi_api_map_value ( miTYPE_SCALAR , &pos[1] ); mi_api_map_value ( miTYPE_SCALAR , &pos[2] ); mi_api_map_field_end (); float radiusPP = 1.0f; if( hasRadiusPP ) radiusPP = *pc.data->data<float>(radiusPPAttr, i); radiusPP = rnd() * 0.3; // define the radius of this element mi_api_map_value ( miTYPE_SCALAR , &radiusPP ); mi_api_map_field_end (); // // compute the color in r, g and b // miScalar r = rnd(); miScalar g = rnd(); miScalar b = rnd(); miColor col; col.r = r; col.g = g; col.b = b; // define the color of this element //mi_api_map_value ( miTYPE_COLOR , &col ); mi_api_map_value ( miTYPE_SCALAR , &r ); mi_api_map_value ( miTYPE_SCALAR , &g ); mi_api_map_value ( miTYPE_SCALAR , &b ); mi_api_map_field_end(); // end the definition of this element mi_api_map_element_end (); } // terminates the map definition and stores it in the DB miTag map_tag = mi_api_map_end ( 0 ); miTag particleObjTag = mi_api_object_end(); miEchoOptions options; memset(&options, 0, sizeof(options)); options.ascii_output = true; options.compressed_output = false; options.dont_echo = false; mi_info("Writing to geodump.mi file."); const char *mode = "w"; FILE *fh = fopen("C:/daten/3dprojects/Maya2013/scenes/geodump.mi", mode); //mi_geoshader_echo_tag(fh, particleObjTag, &options); fclose(fh); mi::shader::Access_map map(map_tag); mi::shader::Map_status status; mi::shader::Map_declaration map_declaration(map, &status); mi::shader::Map_field_id field_id = map_declaration->get_field_id(mi_mem_strdup("color"), &status); if (!status.is_ok()) { mi_error("problems getting field_id for color"); return particleObjTag; } mi_info("Field id %d", field_id); mi::shader::Map_field_type f_type; miUint f_dimension; bool f_is_global; status = map_declaration->get_field_info(field_id, f_type, f_dimension, f_is_global); if (!status.is_ok()) { mi_error("problems get_field_info"); return particleObjTag; } mi_info("Field type %d is global %d", f_type.type(), f_is_global); return particleObjTag; }