Shader color_ramp

Click on the filename to display or download the file.

color_ramp.mi
declare shader 
    color "color_ramp" ( 
        array color "colors" ) 
    version 1 
    apply environment, texture 
end declare 

color_ramp.c
#include "shader.h" 
#include "miaux.h" 
 
#define RAMPSIZE 1024 
 
struct color_ramp { 
    int      i_colors;  
    int      n_colors;  
    miColor colors[1]; 
}; 
 
DLLEXPORT 
int color_ramp_version(void) { return 1; } 
 
DLLEXPORT 
miBoolean color_ramp_init( 
    miState *state, struct color_ramp *params, 
    miBoolean *instance_init_required) 
{ 
    if (params == NULL) {  /* Main shader init (not an instance) */ 
        *instance_init_required = miTRUE; 
    } else {               /* Instance initialization */ 
        int n_colors = *mi_eval_integer(&params->n_colors); 
        miColor *colors =  
            mi_eval_color(params->colors) + *mi_eval_integer(&params->i_colors); 
        miColor *ramp =  
            miaux_user_memory_pointer(state, sizeof(miColor) * RAMPSIZE); 
 
        miaux_piecewise_color_sinusoid(ramp, RAMPSIZE, n_colors, colors); 
    } 
    return miTRUE; 
} 
 
DLLEXPORT 
miBoolean color_ramp_exit(miState *state, void *params) 
{ 
    return miaux_release_user_memory("color_ramp", state, params); 
} 
 
DLLEXPORT 
miBoolean color_ramp ( 
    miColor *result, miState *state, struct color_ramp *params  ) 
{ 
    miColor *ramp = miaux_user_memory_pointer(state, 0); 
    miaux_interpolated_color_lookup( 
        result, ramp, RAMPSIZE, miaux_altitude(state)); 
    return miTRUE; 
} 

color_ramp_util.c
void* miaux_user_memory_pointer(miState *state, int allocation_size) 
{ 
    void **user_pointer; 
    mi_query(miQ_FUNC_USERPTR, state, 0, &user_pointer); 
    if (allocation_size > 0) { 
	*user_pointer = mi_mem_allocate(allocation_size); 
    } 
    return *user_pointer; 
} 
 
void miaux_piecewise_color_sinusoid( 
    miColor result[], int result_count, int key_count, miColor key_values[])  
{ 
    int key, i; 
    for (key = 1; key < key_count; key++) { 
	int start = (int)(key_values[key-1].a * result_count); 
	int end = (int)(key_values[key].a * result_count) - 1; 
	for (i = start; i <= end; i++) { 
	    result[i].r = 
		miaux_sinusoid_fit( 
		    i, start, end, key_values[key-1].r, key_values[key].r); 
	    result[i].g =  
		miaux_sinusoid_fit( 
		    i, start, end, key_values[key-1].g, key_values[key].g); 
	    result[i].b =  
		miaux_sinusoid_fit( 
		    i, start, end, key_values[key-1].b, key_values[key].b); 
	} 
    } 
} 
 
double miaux_sinusoid_fit( 
    double v, double oldmin, double oldmax, double newmin, double newmax) 
{ 
    return miaux_fit(sin(miaux_fit(v, oldmin, oldmax, -M_PI_2, M_PI_2)),  
		     -1, 1,  
		     newmin, newmax); 
} 
 
double miaux_fit( 
    double v, double oldmin, double oldmax, double newmin, double newmax)     
{ 
    return newmin + ((v - oldmin) / (oldmax - oldmin)) * (newmax - newmin); 
} 
 
miBoolean miaux_release_user_memory(char* shader_name, miState *state, void *params) 
{ 
    if (params != NULL) {  /* Shader instance exit */ 
	void **user_pointer;                            
	if (!mi_query(miQ_FUNC_USERPTR, state, 0, &user_pointer)) 
	    mi_fatal("Could not get user pointer in shader exit function %s_exit",  
		     shader_name); 
	mi_mem_release(*user_pointer); 
    } 
    return miTRUE; 
} 
 
void miaux_interpolated_color_lookup(miColor* result, 
				     miColor lookup_table[], int table_size, 
				     miScalar t) 
{ 
    int lower_index = (int)(t * table_size); 
    miColor lower_value = lookup_table[lower_index]; 
    int upper_index = lower_index + 1; 
    miColor upper_value = lookup_table[upper_index]; 
    result->r = miaux_fit(t * table_size, lower_index, upper_index, 
			  lower_value.r, upper_value.r); 
    result->g = miaux_fit(t * table_size, lower_index, upper_index, 
			  lower_value.g, upper_value.g); 
    result->b = miaux_fit(t * table_size, lower_index, upper_index, 
			  lower_value.b, upper_value.b); 
} 
 
float miaux_altitude(miState *state) 
{ 
    miVector ray; 
    mi_vector_to_world(state, &ray, &state->dir); 
    mi_vector_normalize(&ray); 
    return miaux_fit(asin(ray.y), -M_PI_2, M_PI_2, 0.0, 1.0); 
} 

22 April 2008 23:40:49