/****************************************************************************** * Copyright 1986-2004 by mental images GmbH, Fasanenstr. 81, D-10623 Berlin, * Germany. All rights reserved. ****************************************************************************** * Created 10.12.2001 * Module baseshader * Purpose base shaders for Phenomenon writers * * Exports: * mib_illum_hair() * * History: * 10.12.2001: created * * Description: *****************************************************************************/ #include "shader.h" #define MIB_ILLUM_HAIR_VERSION 1 struct mib_illum_hair { 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_hair_version() { return MIB_ILLUM_HAIR_VERSION; } DLLEXPORT miBoolean mib_illum_hair( miColor *result, miState *state, struct mib_illum_hair *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 */ /* illegal call, return to prevent crash */ if(state->type == miRAY_DISPLACE) return miFALSE; /* check if we are a shadow shader */ if (state->type == miRAY_SHADOW) { diffuse = mi_eval_color(¶s->diffuse); result->r *= diffuse->r; result->g *= diffuse->g; result->b *= 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; result->a = 1.0f; /* 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; i 1.0f) dot_nl = 1.0f; /* diffuse term */ sum.r += dot_nl * diffuse->r * 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; }