/****************************************************************************** *****************************************************************************/ #include #include #include /*------------------------------------------ mib_hair_texture_color -------------*/ struct mib_hair_texture_color { miBoolean opaque; }; DLLEXPORT int mib_hair_texture_color_version(void) {return(1);} DLLEXPORT miBoolean mib_hair_texture_color( miColor *result, miState *state, struct mib_hair_texture_color *paras) { miBoolean opaque; opaque = *mi_eval_boolean(¶s->opaque); *result = *(miColor *)&state->tex_list[0]; if (opaque) {result->a = 1.0;} /*mi_info("%f %f %f %f", result->r, result->g, result->b, result->a);*/ return(miTRUE); } struct mib_illum_hair2 { miColor ambience; /* ambient colour multiplier */ miColor ambient; /* ambient colour */ miColor diffuse; /* diffuse colour */ miColor specular; /* specular colour */ miScalar exponent; /* shinyness */ int mode; /* light mode: 0..2 */ int i_light; /* index of first light */ int n_light; /* number of lights */ miTag light[1]; /* list of lights */ }; DLLEXPORT int mib_illum_hair2_version() { return (2); } DLLEXPORT miBoolean mib_illum_hair2( miColor *result, miState *state, struct mib_illum_hair2 *paras) { /* shader parameters */ miColor *ambient; miColor *diffuse; miColor *specular; miScalar exponent; miInteger mode; miInteger i_light; miInteger n_light; miTag *light; miInteger samples; /* for light sampling */ miInteger i; /* for light loop */ miColor lightcol; /* light colour */ miScalar dot_nl; /* for diffuse colour */ miScalar dot_th; /* for specular colour */ miVector l; /* light direction */ miVector h; /* halfway vector */ miScalar spec; /* specular factor */ miVector t = state->derivs[0]; /* tangent to hair */ miVector v = state->dir; /* eye ray */ miVector cross, hair_n, shading_n; /* shading normal */ miColor sum; /* light contribution */ miScalar blend; /* shading normal blend */ miVector norm = state->normal; /* for nulling/restoring */ /* check if we are a shadow shader */ if (state->type == miRAY_SHADOW) { diffuse = mi_eval_color(¶s->diffuse); if (diffuse->a == 1.0) { result->r=result->g=result->b=0; return miFALSE;} else { /* commented out simplistic coloring of shadow */ /* result->r *= diffuse->r; * result->g *= diffuse->g; * result->b *= diffuse->b; */ /* in the following, the shadow color is: * from opaque to .5 transparency, filtered from black to diffuse color * from .5 to full transparency, filtered from diffuse color to white, ie clear */ miScalar f, tmf; miScalar transp = 1 - diffuse->a; if (transp < 0.5) { f = 2 * transp; result->r *= f * diffuse->r; result->g *= f * diffuse->g; result->b *= f * diffuse->b; } else { f = 2 * (transp - 0.5); tmf = 1 - f; result->r *= f + tmf * diffuse->r; result->g *= f + tmf * diffuse->g; result->b *= f + tmf * diffuse->b; } return miTRUE; } } /* tangent is not normalized yet */ mi_vector_normalize(&t); /* get parameters */ *result = *mi_eval_color(¶s->ambience); ambient = mi_eval_color(¶s->ambient); result->r *= ambient->r; result->g *= ambient->g; result->b *= ambient->b; diffuse = mi_eval_color(¶s->diffuse); specular = mi_eval_color(¶s->specular); exponent = *mi_eval_scalar(¶s->exponent); mode = *mi_eval_integer(¶s->mode); i_light = *mi_eval_integer(¶s->i_light); n_light = *mi_eval_integer(¶s->n_light); light = mi_eval_tag(paras->light) + i_light; /* correct light list, if requested */ if (mode == 1) mi_inclusive_lightlist(&n_light, &light, state); else if (mode == 2) mi_exclusive_lightlist(&n_light, &light, state); /* calculate current opacity (0.5 at root, 1.0 at tip) */ /* result->a = 0.5f + state->bary[1] * 0.5f; */ /* replaced with opacity coming in through diffuse alpha */ result->a = diffuse->a; /*mi_info("r=%f g=%f b=%f a=%f", result->r, result->g, result->b, result->a);*/ /* prepare some values */ mi_vector_neg(&v); /* get shading normal */ mi_vector_prod(&cross, &state->normal_geom, &t); mi_vector_prod(&hair_n, &t, &cross); blend = mi_vector_dot(&state->normal_geom, &t); shading_n.x = (1.0f-blend)*hair_n.x + blend*state->normal_geom.x; shading_n.y = (1.0f-blend)*hair_n.y + blend*state->normal_geom.y; shading_n.z = (1.0f-blend)*hair_n.z + blend*state->normal_geom.z; mi_vector_normalize(&shading_n); /* null state->normal for now, for sampling lights */ /* we leave state->pri to avoid losing self-intersection */ /* handling. */ state->normal.x = state->normal.y = state->normal.z = 0.0f; /* loop over lights */ for (i=0; ir * lightcol.r; sum.g += dot_nl * diffuse->g * lightcol.g; sum.b += dot_nl * diffuse->b * lightcol.b; /* find the halfway vector h */ mi_vector_add(&h, &v, &l); mi_vector_normalize(&h); /* specular coefficient from auk paper */ dot_th = mi_vector_dot(&t, &h); spec = 1.0 - dot_th*dot_th; spec = pow(spec, exponent / 2.0); /* specular colour */ if (spec > 0.0) { sum.r += spec * specular->r * lightcol.r; sum.g += spec * specular->g * lightcol.g; sum.b += spec * specular->b * lightcol.b; } } /* add it in */ if (samples) { result->r += sum.r / samples; result->g += sum.g / samples; result->b += sum.b / samples; } } /* restore state->normal */ state->normal = norm; /* if we are translucent, trace more rays */ if (result->a < 0.9999) { miScalar alphafactor; miColor col = {0.0, 0.0, 0.0, 0.0}; mi_trace_transparent(&col, state); alphafactor = 1.0f - result->a; result->r = alphafactor * col.r + result->a * result->r; result->g = alphafactor * col.g + result->a * result->g; result->b = alphafactor * col.b + result->a * result->b; result->a += alphafactor * col.a; } return miTRUE; }