All of the user defined functions must return TRUE on success, and return FALSE on failure.
Assuming that the ALIAS OpenRender Template file is used, there are only three functions to be written:
INIT(), FREE() and CALC().The rest of this section assumes that the ALIAS OpenRender Template is being modified to create a new module. Writing an ALIAS OpenRender C Code Module from scratch should not be attempted without training.
In the prototype code outlined below, comments that appear in bold text are locations where you should perform certain calculations, or insure that an Alias AR_???Data structure gets updated with the appropriate values.
All prototypes in this section should be available on-line under
/usr/alias/ocr.
static AR_Boolean INIT( INFO_TYPE *pInfo )-This function must return TRUE on success and FALSE on failure. Its purpose is to initialize any variables in your INFO structure that do not have a corresponding field in the SDL file. In most cases, this is an empty function. Values that should be set in this function include:
static AR_Boolean FREE( INFO_TYPE *pInfo)-This function must return TRUE. Its purpose is to free any memory that has been allocated and placed into the INFO structure so that the INFO structure itself can be freed.Note: This function should not attempt to free the INFO structure itself.
static int CALC (
AR_ShaderInfo *pShader,
AR_GeometryInfo *pGeometry,
AR_ShadeData *pShadeData,
AR_OCR_ObjectInfo *object_info,
void *ni,
void *rt_ray_rec
)
AR_GeometryInfo structure), walks through the light list (specified in the AR_ShadeData structure), sums the intensities of the lights and adds the lights' ambient and diffuse values, factors in transparency, and adds the specular term to arrive at the final color for the point (results are placed in the AR_ShadeData structure).Before calling each light, the shader routine should set three flags to FALSE:
light_data.ambient, light_data.diffuse, and light_data.specular. These three flags indicate what kind of contribution the current light makes to the point being shaded, and they are set by each light routine. An ambient light only sets light_data.ambient to TRUE; a point light sets light_data.diffuse and light_data.specular to TRUE.The specular component (if any) is applied according to the shading model the shader implements. For example, the Lambert shading model does not implement a specular component, so the specular portion is not factored into that shading model's results.
The
AR_ShaderInfo structure points to your INFO structure from the user_shader_info field. When accessing the INFO structure through this pointer, the pointer should be cast to the INFO structure type. This function should always return TRUE; it is not allowed to fail.The last three arguments to this function are used strictly for raytracing and are required to calculate the reflected ray color.
During the rendering phase, once you are shading a single ray, the order of calling the CALC routines is: Textures, Shaders, Lights. Alias calls and calculates all textures referenced in the standard Alias shader. The calculated values from the textures are placed in
AR_ShadeData and then passed to the shader CALC function. If your Shader INFO structure contains any textures, you must call their CALC functions at the start of your shader CALC function by setting up an AR_TextureData structure and calling OCR_INVOKE_MAPPING(). Then your Shader routine should walk the light list, calling each light in turn. Each light returns an AR_LightData structure that contains the lighting contribution of the current light.
int CALC (
AR_ShaderInfo *pShader,
AR_GeometryInfo *pGeometry,
AR_ShadeData *pShadeData,
AR_OCR_ObjectInfo *object_info,
void *ni,
void *rt_ray_rec
)
{
AR_Rgb ambient_term;
AR_Rgb diffuse_term;
AR_Rgb specular_term;
AR_Rgba result;
AR_Rgba rgba;
INFO_TYPE *pInfo;
AR_LightData light_data;
AR_LightInfo *pLight;
AR_LightList *pLL;
double diffuse_coeff;
double specular_coeff;
pInfo = (INFO_TYPE *) pShader->user_shader_info;
/* call OCR_INVOKE_MAPPING() for any texturable fields in your
structure */
ambient_term.r = ambient_term.g = ambient_term.b = 0.0;
diffuse_term.r = diffuse_term.g = diffuse_term.b = 0.0;
specular_term.r = specular_term.g = specular_term.b = 0.0;
for( pLL=pShadeData->lights; pLL!=NULL; pLL=pLL->next )
{
pLight = pLL->light;
if( !(pLight->active)) continue;
if( !(pLight->rtns->calc) ) continue;
light_data.ambient = light_data.diffuse = light_data.specular
= FALSE;
light_data.user_data = NULL;
light_data.computed_cosln = light_data.force = FALSE;
if( !((pLight->rtns->calc)( pShadeData, &light_data, pLight )))
continue;
if( light_data.ambient )
{
ambient_term.r += light_data.intensity.r
* pShadeData->surfColor->r;
ambient_term.g += light_data.intensity.g
* pShadeData->surfColor->g;
ambient_term.b += light_data.intensity.b
* pShadeData->surfColor->b;
}
if( light_data.diffuse )
{
/* Calculate the diffuse contribution here and ADD results to
'diffuse_term'. */
}
if( light_data.specular ) {
/* Calculate the specular contribution here and ADD results to
'specular_term'. */
}
}
result.r = ambient_term.r + diffuse_term.r;
result.g = ambient_term.g + diffuse_term.g;
result.b = ambient_term.b + diffuse_term.b;
result.a = 255.0;
/* Calculate Transparency */
if ( pShadeData->surfTrans.r != 0.0 ||
pShadeData->surfTrans.g != 0.0 ||
pShadeData->surfTrans.b != 0.0)
{
/* The "transcol" is the color of the objects BEHIND the */
/* current surface. */
result.r +=pShadeData->surfTrans.r * (pShadeData->transcol->r -
result.r);
result.g +=pShadeData->surfTrans.g * (pShadeData->transcol->g -
result.g);
result.b +=pShadeData->surfTrans.b * (pShadeData->transcol->b -
result.b);
result.a +=pShadeData->surfTrans.a * (pShadeData->transcol->a -
result.a);
}
/* The specular term must be added after the transparency */
/* calculation or the specular will be incorrectly affected */
/* by the color of the objects behind the transparent surface. */
result.r += specular_term.r;
/* add the specular colour */
result.g += specular_term.g;
result.b += specular_term.b;
/* Add the surface incandescence. It is independent */
/* of the surf colour. */
/* THE SETTING OF pShadeData -> transcol MUST BE THE LAST THING DONE
BEFORE THE RETURN STATEMENT. */
pShadeData->transcol->r = result.r + pShadeData->incandescence.r;
pShadeData->transcol->g = result.g + pShadeData->incandescence.g;
pShadeData->transcol->b = result.b + pShadeData->incandescence.b;
pShadeData->transcol->a = result.a;
return (TRUE);
}
static int CALC (
AR_ShadeData *pShadeData,
AR_LightData *pLightData,
AR_LightInfo *pLightInfo
)
AR_ShadeData structure) and a light (specified by the AR_LightInfo structure). It then calculates the light's intensity at that point. The result is placed in the AR_LightData structure. If the light does contribute intensity to the point, TRUE is returned. If the light does not contribute intensity to the point (for example, if the point is too far from the light source, or shadowed from the light source), then FALSE is returned. Your INFO structure is pointed to in the AR_LightInfo structure in the user_light_info field. When accessing your INFO structure through this pointer, the pointer should be cast to your INFO structure type.Each light must set the
pLightData->[ambient|diffuse|specular] flags according to the type of contribution they make to the current point. If the light makes a diffuse and/or a specular contribution, a normalized direction vector from the point of intersection to the center of the light must be generated and placed into AR_LightData. The pLightData->direction field is used in diffuse and specular shading computations in the shader CALC function.
int CALC (
AR_ShadeData *pShadeData,
AR_LightData *pLightData,
AR_LightInfo *pLightInfo
)
{
INFO_TYPE *Light_Info;
AR_ShadeData *hold_for_recursion;
float intensity;
double length;
Light_Info = (INFO_TYPE *)pLightInfo->user_light_info;
if( !Light_Info ) return ( FALSE );
/* pLightData->direction MUST be set if either specular or diffuse */
/* are set to TRUE below. In this case, the light is hard coded to */
/* be at (32, 32, 32). */
pLightData->direction.x = 32.0 - pShadeData->crosspt->x;
pLightData->direction.y = 32.0 - pShadeData->crosspt->y;
pLightData->direction.z = 32.0 - pShadeData->crosspt->z;
OCR_NORMALIZE( length, pLightData->direction );
/* You must calculate the light's intensity into 'intensity' here. */
/* It should be a value >= 0.0. */
if( intensity < 0.0001 ) return ( FALSE ); /* no contribution */
/* The following 3 flags MUST be set according to the type of
contribution */
/* this light can make to the point being shaded. */
pLightData->ambient = FALSE;
pLightData->diffuse = TRUE;
pLightData->specular = TRUE;
/* The final intensity of the light MUST be placed in pLightData-
>intensity. */
pLightData->intensity.r = pLightInfo->transformed_color.r *
intensity;
pLightData->intensity.g = pLightInfo->transformed_color.g *
intensity;
pLightData->intensity.b = pLightInfo->transformed_color.b *
intensity;
return ( TRUE );
}
static int CALC ( AR_TextureData *texture )-This function is given the world space coordinates and parametric coordinates of a point (specified in the AR_TextureData structure). It then calculates the color (including alpha channel) at that point (results are placed in the AR_TextureData structure). Your INFO structure is pointed to by texture->TDdata->user_texture_info. When accessing your INFO structure through this pointer, the pointer should be cast to your INFO structure type.This function should always return TRUE upon success. If there is a problem, the texture routine should return FALSE and it should not modify
AR_TextureData->TDcolor, since the color has already been set to the texture's out value.NOTE: Textures require extra type specifications in the ALIAS OpenRender C code modules. When writing a texture, locate the #defines at the top of the file:
#define TEXTURE_STATUS FUNC_TEXTURE
#define TEXTURE_TYPE PARAMETRIC_MAP
#define TEXTURE_ABSOLUTE FALSE
TEXTURE_TYPE can be PARAMETRIC_MAP, SOLID_3D_MAP, or ENVIRONMENT_MAP: most textures are PARAMETRIC_MAP.
SOLID_3D_MAP textures are textures that operate purely in 3D space and require no information about the object's (u,v) coordinates (setting this can produce efficiencies because (u,v) coordinates do not need to be stored nor computed).
ENVIRONMENT_MAP textures are textures that use the reflected ray to calculate the color of the texture at any point. Textures that are ENVIRONMENT_MAPs cannot be used for bump or displacement mapping.
TEXTURE_ABSOLUTE can be TRUE or FALSE. Textures that use parametric mapping (the u, v coordinates) must set this to FALSE. Environment maps and solid textures must set this flag to TRUE.
int CALC ( AR_TextureData *texture )
{
AR_TextureInfo *pInfo;
INFO_TYPE *pData;
float u, v;
AR_Rgba result;
pInfo = texture->TDdata;
pData = (INFO_TYPE *)( pInfo->user_texture_info );
u = texture->TDu;
v = texture->TDv;
/* Using the u,v values, calculate the texture color here. */
blurmult = texture->TDblurmult;
bluroffset = texture->TDbluroffset;
/* This assumes that the color has been placed in 'result'. */
/* texture->TDcolor MUST be set before returning. */
texture->TDcolor->r = result.r;
texture->TDcolor->g = result.g;
texture->TDcolor->b = result.b;
texture->TDcolor->a = result.a;
return( TRUE );
}
int CALC( AR_TextureData *texture )
{
INFO_TYPE *pData;
AR_TextureInfo *pInfo;
AR_Point *pt;
AR_Point pt2;
AR_Vector *norm;
AR_Rgba result;
pInfo = texture->TDdata;
pData = (INFO_TYPE *)( pInfo->user_texture_info );
pt = texture->TDhit;
norm = texture->TDnormal;
OCR_init_texture_transforms( pInfo, &pData->invdet);
/* Assuming pData->invdet exists. */
/* Define the texture space coordinates for the solid texture */
pt2.x = pt->x;
pt2.y = pt->y;
pt2.z = pt->z;
OCR_transform_point(&pt2, pInfo->invcurrTM);
/* Using the pt2.[x,y,z] and/or the normal (in 'norm'), calculate */
/* the texture color here. */
/* This assumes that the color has been placed in 'result'. */
/* texture->TDcolor MUST be set before returning. */
texture->TDcolor->r = result.r;
texture->TDcolor->g = result.g;
texture->TDcolor->b = result.b;
texture->TDcolor->a = result.a;
return (TRUE);
}
int CALC ( AR_TextureData *texture )
{
float length;
INFO_TYPE *pData;
AR_TextureInfo *pInfo;
AR_Point *pt;
AR_Vector norm;
AR_Rgba value;
pInfo = texture->TDdata;
pData = (INFO_TYPE *)( pInfo->user_texture_info );
OCR_init_texture_transforms( pInfo, NULL );
pt = texture->TDhit;
norm.x = texture->TDray->x;
norm.y = texture->TDray->y;
norm.z = texture->TDray->z;
/* Define the texture space coordinates for the solid texture */
pt2.x = pt->x;
pt2.y = pt->y;
pt2.z = pt->z;
OCR_transform_point(&pt2, pInfo->invcurrTM);
OCR_transform_vector(&norm, pInfo->invcurrTM);
/* Based on the normal and/or the point, calculate the value of the
environment */
/* function here. Place the calculated color in 'value'. In this
example, the */
/* Alpha channel is calculated by computing the luminance of the
color. */
texture->TDcolor->r = value.r;
texture->TDcolor->g = value.g;
texture->TDcolor->b = value.b;
texture->TDcolor->a
= OCR_NTSC_LUMINANCE(value.r, value.g, value.b);
return( FALSE );
}