Hint support (only for first hiearchic level and shadow rays, lets see if this is useful)

That means each shadow ray tests:
	1st: last hit face
	2nd: last hit object
	3rd: tree of all objects
This commit is contained in:
Andre Susano Pinto
2009-07-08 15:34:41 +00:00
parent f90a0b8383
commit f13d11ab71
4 changed files with 96 additions and 21 deletions

View File

@@ -31,7 +31,10 @@
#ifndef RE_RAYTRACE_H
#define RE_RAYTRACE_H
#define RT_USE_HINT /* 1 level hint */
#define RE_RAYCOUNTER
#ifdef RE_RAYCOUNTER
typedef struct RayCounter RayCounter;
@@ -42,9 +45,7 @@ struct RayCounter
{
unsigned long long test, hit;
} faces, bb, raycast;
unsigned long long rayshadow_last_hit_optimization;
} faces, bb, raycast, raytrace_hint, rayshadow_last_hit;
};
/* #define RE_RC_INIT(isec, shi) (isec).count = re_rc_counter+(shi).thread */
@@ -68,6 +69,9 @@ extern RayCounter re_rc_counter[];
/* Internals about raycasting structures can be found on intern/raytree.h */
typedef struct RayObject RayObject;
typedef struct Isect Isect;
typedef struct RayTraceHint RayTraceHint;
struct DerivedMesh;
struct Mesh;
@@ -97,7 +101,6 @@ struct Isect
int bv_index[6];
float idot_axis[3];
float dist;
/* float end[3]; - not used */
@@ -107,11 +110,14 @@ struct Isect
{
void *ob;
void *face;
/* RayObject *obj; */
}
hit, orig;
RayObject *last_hit; /* last hit optimization */
#ifdef RT_USE_HINT
RayTraceHint *hint, *hit_hint;
#endif
short isect; /* which half of quad */
short mode; /* RE_RAY_SHADOW, RE_RAY_MIRROR, RE_RAY_SHADOW_TRA */

View File

@@ -317,23 +317,34 @@ int RE_rayobject_raycast(RayObject *r, Isect *isec)
/* Last hit heuristic */
if(isec->mode==RE_RAY_SHADOW && isec->last_hit && RE_rayobject_intersect(isec->last_hit, isec))
if(isec->mode==RE_RAY_SHADOW && isec->last_hit)
{
RE_RC_COUNT(isec->raycounter->raycast.hit);
RE_RC_COUNT(isec->raycounter->rayshadow_last_hit_optimization );
return 1;
RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.test);
if(RE_rayobject_intersect(isec->last_hit, isec))
{
RE_RC_COUNT(isec->raycounter->raycast.hit);
RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.hit);
return 1;
}
}
#ifdef RE_RAYCOUNTER
#ifdef RT_USE_HINT
isec->hit_hint = 0;
#endif
if(RE_rayobject_intersect(r, isec))
{
#ifdef RE_RAYCOUNTER
RE_RC_COUNT(isec->raycounter->raycast.hit);
#endif
#ifdef RT_USE_HINT
isec->hint = isec->hit_hint;
#endif
return 1;
}
return 0;
#else
return RE_rayobject_intersect(r, isec);
#endif
}
int RE_rayobject_intersect(RayObject *r, Isect *i)
@@ -398,15 +409,19 @@ void RE_RC_INFO(RayCounter *info)
printf("\n");
printf("Primitives tests: %llu\n", info->faces.test );
printf("Primitives hits: %llu\n", info->faces.hit );
printf("------------------------------------\n");
printf("Shadow last-hit tests per ray: %f\n", info->rayshadow_last_hit.test / ((float)info->raycast.test) );
printf("Shadow last-hit hits per ray: %f\n", info->rayshadow_last_hit.hit / ((float)info->raycast.test) );
printf("\n");
printf("Shadow Last hit reuse: %llu\n", info->rayshadow_last_hit_optimization);
printf("\n");
printf("Primitives tests per ray: %f\n", info->faces.test / ((float)info->raycast.test) );
printf("Primitives hits per ray: %f\n", info->faces.hit / ((float)info->raycast.test) );
printf("Hint tests per ray: %f\n", info->raytrace_hint.test / ((float)info->raycast.test) );
printf("Hint hits per ray: %f\n", info->raytrace_hint.hit / ((float)info->raycast.test) );
printf("\n");
printf("BB tests per ray: %f\n", info->bb.test / ((float)info->raycast.test) );
printf("BB hits per ray: %f\n", info->bb.hit / ((float)info->raycast.test) );
printf("\n");
printf("Primitives tests per ray: %f\n", info->faces.test / ((float)info->raycast.test) );
printf("Primitives hits per ray: %f\n", info->faces.hit / ((float)info->raycast.test) );
printf("------------------------------------\n");
}
void RE_RC_MERGE(RayCounter *dest, RayCounter *tmp)
@@ -420,7 +435,11 @@ void RE_RC_MERGE(RayCounter *dest, RayCounter *tmp)
dest->raycast.test += tmp->raycast.test;
dest->raycast.hit += tmp->raycast.hit;
dest->rayshadow_last_hit_optimization += tmp->rayshadow_last_hit_optimization;
dest->rayshadow_last_hit.test += tmp->rayshadow_last_hit.test;
dest->rayshadow_last_hit.hit += tmp->rayshadow_last_hit.hit;
dest->raytrace_hint.test += tmp->raytrace_hint.test;
dest->raytrace_hint.hit += tmp->raytrace_hint.hit;
}
#endif

View File

@@ -160,6 +160,9 @@ static int dfs_raycast_stack(BVHNode *root, Isect *isec)
{
BVHNode *stack[DFS_STACK_SIZE];
int hit = 0, stack_pos = 0;
#ifdef RT_USE_HINT
BVHNode *last_processed_node = 0;
#endif
stack[stack_pos++] = root;
@@ -170,19 +173,29 @@ static int dfs_raycast_stack(BVHNode *root, Isect *isec)
{
if(RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX)
{
last_processed_node = node;
//push nodes in reverse visit order
if(isec->idot_axis[node->split_axis] < 0.0f)
{
int i;
for(i=0; i<BVH_NCHILDS; i++)
if(node->child[i] == 0) break;
else stack[stack_pos++] = node->child[i];
else
#ifdef RT_USE_HINT
if(node->child[i] != (BVHNode*)isec->hint)
#endif
stack[stack_pos++] = node->child[i];
}
else
{
int i;
for(i=0; i<BVH_NCHILDS; i++)
if(node->child[i] != 0) stack[stack_pos++] = node->child[i];
if(node->child[i] != 0
#ifdef RT_USE_HINT
&& node->child[i] != (BVHNode*)isec->hint
#endif
)
stack[stack_pos++] = node->child[i];
else break;
}
assert(stack_pos <= DFS_STACK_SIZE);
@@ -190,7 +203,19 @@ static int dfs_raycast_stack(BVHNode *root, Isect *isec)
}
else
{
hit |= RE_rayobject_intersect( (RayObject*)node, isec);
int ghit;
#ifdef RT_USE_HINT
RayTraceHint *b_hint = isec->hint;
isec->hint = 0;
#endif
ghit = RE_rayobject_intersect( (RayObject*)node, isec);
#ifdef RT_USE_HINT
isec->hint = b_hint;
if(ghit)
isec->hit_hint = (RayTraceHint*)last_processed_node;
#endif
hit |= ghit;
if(hit && isec->mode == RE_RAY_SHADOW) return hit;
}
}
@@ -200,7 +225,26 @@ static int dfs_raycast_stack(BVHNode *root, Isect *isec)
static int bvh_intersect_stack(BVHTree *obj, Isect *isec)
{
if(RayObject_isAligned(obj->root))
{
#ifdef RT_USE_HINT
if(isec->hint)
{
int hit;
RE_RC_COUNT(isec->raycounter->raytrace_hint.test);
hit = dfs_raycast_stack((BVHNode*) isec->hint, isec);
if(hit)
{
RE_RC_COUNT(isec->raycounter->raytrace_hint.hit);
if(isec->mode == RE_RAY_SHADOW) return hit;
}
else isec->hint = 0; //Clear HINT on non-hit?, that sounds good, but no tests where made
return hit | dfs_raycast_stack(obj->root, isec);
}
#endif
return dfs_raycast_stack(obj->root, isec);
}
else
return RE_rayobject_intersect( (RayObject*)obj->root, isec);
}

View File

@@ -606,6 +606,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo
isec.labda = dist_mir > 0 ? dist_mir : RE_RAYTRACE_MAXDIST;
isec.mode= RE_RAY_MIRROR;
isec.skip = RE_SKIP_VLR_NEIGHBOUR;
isec.hint = 0;
isec.orig.ob = obi;
isec.orig.face = vlr;
@@ -1511,6 +1512,7 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)
isec.mode= RE_RAY_MIRROR;
isec.orig.ob = ship->obi;
isec.orig.face = ship->vlr;
isec.hint = 0;
RE_RC_INIT(isec, shi);
for(a=0; a<8*8; a++) {
@@ -1720,6 +1722,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac)
isec.orig.ob = shi->obi;
isec.orig.face = shi->vlr;
isec.skip = RE_SKIP_VLR_NEIGHBOUR;
isec.hint = 0;
isec.hit.ob = 0;
isec.hit.face = 0;
@@ -1854,6 +1857,7 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac)
isec.orig.ob = shi->obi;
isec.orig.face = shi->vlr;
isec.skip = RE_SKIP_VLR_NEIGHBOUR;
isec.hint = 0;
isec.hit.ob = 0;
isec.hit.face = 0;
@@ -2290,6 +2294,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
RE_RC_INIT(isec, *shi);
if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA;
else isec.mode= RE_RAY_SHADOW;
isec.hint = 0;
if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW))
isec.lay= lar->lay;
@@ -2375,6 +2380,7 @@ static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float
/* setup isec */
RE_RC_INIT(isec, *shi);
isec.mode= RE_RAY_SHADOW_TRA;
isec.hint = 0;
if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1;