Monday, April 11, 2011

Writing mental ray shaders: Set Range Utility

Goal
Make and/or improve on the set range utility found in maya. 

Methodology
1. Given an oldmin and oldmax, find the range by oldmax - oldmin.
2. Given an newmin and newmin, find the range by newmax - newmin.
3. For a given point P, find the range of P by P - oldmin.
4. Find the current_factor by (Step3/Step1)
5. Find the new_factor by (Step4 * Step2) + newmin


Quick Test
1. Given a distance of 20 to 80
2. Map to new range from 0 to 10
3. Lets use a value of 50
4. (50 - 20) / (80 - 20) = 30 / 60 = 0.5
5. 0.5 * (10 - 0) + 0 = 5 = Works out fine.

Mi Source
declare shader
 color "set_range" (
  vector "value"  default 0 0 0,
  vector "oldmin"  default 0 0 0,
  vector "oldmax"  default 0 0 0,
  vector "newmin"  default 0 0 0,
  vector "newmax"  default 1 1 1,
 )
apply material
end declare

C Source
#include "shader.h"

struct set_range {
 miVector value;
 miVector oldmin;
 miVector oldmax;
 miVector newmin;
 miVector newmax;
 };

miBoolean set_range(miColor *result, miState *state, struct set_range *params) {
 miVector *value = mi_eval_vector(&params->value);
 miVector *oldmin = mi_eval_vector(&params->oldmin);
 miVector *oldmax = mi_eval_vector(&params->oldmax);
 miVector *newmin = mi_eval_vector(&params->newmin);
 miVector *newmax = mi_eval_vector(&params->newmax);
 result->r = newmin->x + ((value->x - oldmin->x)/(oldmax->x - oldmin->x)) * (newmax->x - newmin->x);
 result->g = newmin->y + ((value->y - oldmin->y)/(oldmax->y - oldmin->y)) * (newmax->y - newmin->y);
 result->b = newmin->z + ((value->z - oldmin->z)/(oldmax->z - oldmin->z)) * (newmax->z - newmin->z);
 return miTRUE;
 }

Notes
Note that i choose to use vectors for all my inputs, its a design choice as its better to have more than to have less. It be a real pain if I have to create 3 nodes just to correct a color.

0 comments:

Post a Comment