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:
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user