*Added output of BB/primitves test/hits

*"Added" SCE_PASS_RAYHITS to visually see each pixel primitive and BB tests (not-completed for UI)
*Added runtime exchange of tree structure
*Removed FLOAT_EPSILON from BLI_bvhkdop BB's
This commit is contained in:
2009-07-06 13:27:40 +00:00
parent abc44f720a
commit ba1f3323bf
11 changed files with 188 additions and 56 deletions

View File

@@ -26,6 +26,7 @@ class RENDER_PT_shading(RenderButtonsPanel):
colsub = col.column()
colsub.active = rd.render_raytracing
colsub.itemR(rd, "raytrace_structure", text="Structure")
colsub.itemR(rd, "raytrace_tree_type", text="Tree Type")
colsub.itemR(rd, "octree_resolution", text="Octree")
col.itemR(rd, "dither_intensity", text="Dither", slider=True)

View File

@@ -161,6 +161,8 @@ typedef struct SceneRenderLayer {
#define SCE_PASS_RADIO 8192 /* Radio removed, can use for new GI? */
#define SCE_PASS_MIST 16384
#define SCE_PASS_RAYHITS 32768
/* note, srl->passflag is treestore element 'nr' in outliner, short still... */
@@ -233,7 +235,8 @@ typedef struct RenderData {
/* render engine, octree resolution */
short renderer, ocres;
short raystructure;
short pad4[3];
short raytrace_tree_type;
short pad4[2];
/**
* What to do with the sky/background. Picks sky/premul/key
@@ -675,6 +678,11 @@ typedef struct Scene {
#define R_RAYSTRUCTURE_SINGLE_OCTREE 2
#define R_RAYSTRUCTURE_SINGLE_BVH 3
/* raytrace tree type */
#define R_RAYTRACE_TREE_BVH 0
#define R_RAYTRACE_TREE_BLIBVH 1
#define R_RAYTRACE_TREE_BIH 2
/* scemode (int now) */
#define R_DOSEQ 0x0001
#define R_BG_RENDER 0x0002

View File

@@ -293,6 +293,12 @@ void rna_def_scene_render_data(BlenderRNA *brna)
{R_RAYSTRUCTURE_SINGLE_BVH, "{R_RAYSTRUCTURE_SINGLE_BVH", 0, "Single BVH", "BVH of all primitives (no instance support)"},
{R_RAYSTRUCTURE_SINGLE_OCTREE, "{R_RAYSTRUCTURE_SINGLE_OCTREE", 0, "Octree", "Octree of all primitives (no instance support)"},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem raytrace_tree_type_items[] = {
{R_RAYTRACE_TREE_BVH, "{R_RAYTRACE_TREE_BVH", 0, "BVH", "rayobject_bvh.c"},
{R_RAYTRACE_TREE_BLIBVH, "{R_RAYTRACE_TREE_BLIBVH", 0, "BLIbvh", "rayobject_blibvh.c"},
{R_RAYTRACE_TREE_BIH, "{R_RAYSTRUCTURE_SINGLE_BVH", 0, "BIH", "rayobject_bih.c"},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem fixed_oversample_items[] = {
{5, "OVERSAMPLE_5", 0, "5", ""},
@@ -694,6 +700,12 @@ void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_enum_items(prop, raytrace_structure_items);
RNA_def_property_ui_text(prop, "Raytrace Acceleration Structure", "Type of raytrace accelerator structure.");
RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
prop= RNA_def_property(srna, "raytrace_tree_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "raytrace_tree_type");
RNA_def_property_enum_items(prop, raytrace_tree_type_items);
RNA_def_property_ui_text(prop, "Raytrace tree type", "Type of raytrace accelerator structure.");
RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
prop= RNA_def_property(srna, "antialiasing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_OSA);

View File

@@ -31,12 +31,43 @@
#ifndef RE_RAYTRACE_H
#define RE_RAYTRACE_H
#define RE_RAY_COUNTER
#define RE_RAYCOUNTER
#ifdef RE_RAYCOUNTER
typedef struct RayCounter RayCounter;
struct RayCounter
{
struct
{
unsigned long long test, hit;
} faces, bb, raycast;
unsigned long long rayshadow_last_hit_optimization;
};
/* #define RE_RC_INIT(isec, shi) (isec).count = re_rc_counter+(shi).thread */
#define RE_RC_INIT(isec, shi) (isec).raycounter = &((shi).raycounter)
void RE_RC_INFO (RayCounter *rc);
void RE_RC_MERGE(RayCounter *rc, RayCounter *tmp);
#define RE_RC_COUNT(var) (var)++
extern RayCounter re_rc_counter[];
#else
#define RE_RC_INIT(isec,shi)
#define RE_RC_INFO(rc)
#define RE_RC_MERGE(dest,src)
#define RE_RC_COUNT(var)
#endif
/* Internals about raycasting structures can be found on intern/raytree.h */
typedef struct RayObject RayObject;
typedef struct Isect Isect;
typedef struct RayCounter RayCounter;
struct DerivedMesh;
struct Mesh;
@@ -50,7 +81,6 @@ void RE_rayobject_free(RayObject *r);
RayObject* RE_rayobject_octree_create(int ocres, int size);
RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob);
#define RE_rayobject_tree_create RE_rayobject_bvh_create
RayObject* RE_rayobject_blibvh_create(int size); /* BLI_kdopbvh.c */
RayObject* RE_rayobject_bvh_create(int size); /* rayobject_bvh.c */
RayObject* RE_rayobject_bih_create(int size); /* rayobject_bih.c */
@@ -93,38 +123,11 @@ struct Isect
void *userdata;
#ifdef RE_RAY_COUNTER
RayCounter *count;
#endif
};
#ifdef RE_RAYCOUNTER
struct RayCounter
{
struct
{
unsigned long long test, hit;
} intersect_rayface, raycast;
unsigned long long rayshadow_last_hit_optimization;
};
void RE_RC_INIT (RayCounter *rc);
void RE_RC_MERGE(RayCounter *rc, RayCounter *tmp);
#define RE_RC_COUNT(var) (var)++
#else
#define RE_RC_INIT(rc)
#define RE_RC_MERGE(dest,src)
#define RE_RC_COUNT(var)
RayCounter *raycounter;
#endif
};
/* ray types */
#define RE_RAY_SHADOW 0

View File

@@ -30,6 +30,7 @@
#ifndef RE_SHADER_EXT_H
#define RE_SHADER_EXT_H
#include "RE_raytrace.h" /* For RE_RAYCOUNTER */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* this include is for shading and texture exports */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
@@ -57,6 +58,7 @@ typedef struct ShadeResult
float nor[3];
float rad[3];
float winspeed[4];
float rayhits[4];
} ShadeResult;
/* only here for quick copy */
@@ -178,6 +180,10 @@ typedef struct ShadeInput
struct Group *light_override;
struct Material *mat_override;
#ifdef RE_RAYCOUNTER
RayCounter raycounter;
#endif
} ShadeInput;

View File

@@ -347,6 +347,13 @@ static char *get_pass_name(int passtype, int channel)
if(channel==-1) return "Mist";
return "Mist.Z";
}
if(passtype == SCE_PASS_RAYHITS)
{
if(channel==-1) return "Rayhits";
if(channel==0) return "Rayhits.R";
if(channel==1) return "Rayhits.G";
return "Rayhits.B";
}
return "Unknown";
}
@@ -398,6 +405,8 @@ static int passtype_from_name(char *str)
if(strcmp(str, "Mist")==0)
return SCE_PASS_MIST;
if(strcmp(str, "RAYHITS")==0)
return SCE_PASS_RAYHITS;
return 0;
}
@@ -523,7 +532,7 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int
rl->lay= srl->lay;
rl->lay_zmask= srl->lay_zmask;
rl->layflag= srl->layflag;
rl->passflag= srl->passflag;
rl->passflag= srl->passflag | SCE_PASS_RAYHITS;
rl->pass_xor= srl->pass_xor;
rl->light_override= srl->light_override;
rl->mat_override= srl->mat_override;
@@ -565,6 +574,8 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int
render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB);
if(srl->passflag & SCE_PASS_MIST)
render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST);
if(rl->passflag & SCE_PASS_RAYHITS)
render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS);
}
/* sss, previewrender and envmap don't do layers, so we make a default one */

View File

@@ -54,10 +54,14 @@ float RE_rayobject_bb_intersect(const Isect *isec, const float *_bb)
float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2];
float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2];
RE_RC_COUNT(isec->raycounter->bb.test);
if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return FLT_MAX;
if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return FLT_MAX;
if(t1x > isec->labda || t1y > isec->labda || t1z > isec->labda) return FLT_MAX;
RE_RC_COUNT(isec->raycounter->bb.hit);
dist = t1x;
if (t1y > dist) dist = t1y;
if (t1z > dist) dist = t1z;
@@ -157,7 +161,7 @@ static int intersect_rayface(RayFace *face, Isect *is)
if(is->orig.ob == face->ob && is->orig.face == face->face)
return 0;
RE_RC_COUNT(is->count->intersect_rayface.test);
RE_RC_COUNT(is->raycounter->faces.test);
VECCOPY(co1, face->v1);
VECCOPY(co2, face->v2);
@@ -276,7 +280,7 @@ static int intersect_rayface(RayFace *face, Isect *is)
}
#endif
RE_RC_COUNT(is->count->intersect_rayface.hit);
RE_RC_COUNT(is->raycounter->faces.hit);
is->isect= ok; // wich half of the quad
is->labda= labda;
@@ -294,7 +298,7 @@ static int intersect_rayface(RayFace *face, Isect *is)
int RE_rayobject_raycast(RayObject *r, Isect *isec)
{
int i;
RE_RC_COUNT(isec->count->raycast.test);
RE_RC_COUNT(isec->raycounter->raycast.test);
/* Setup vars used on raycast */
isec->labda *= Normalize(isec->vec);
@@ -315,15 +319,15 @@ 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))
{
RE_RC_COUNT(isec->count->raycast.hit);
RE_RC_COUNT(isec->count->rayshadow_last_hit_optimization );
RE_RC_COUNT(isec->raycounter->raycast.hit);
RE_RC_COUNT(isec->raycounter->rayshadow_last_hit_optimization );
return 1;
}
#ifdef RE_RAYCOUNTER
if(RE_rayobject_intersect(r, isec))
{
RE_RC_COUNT(isec->count->raycast.hit);
RE_RC_COUNT(isec->raycounter->raycast.hit);
return 1;
}
return 0;
@@ -383,16 +387,40 @@ void RE_rayobject_merge_bb(RayObject *r, float *min, float *max)
}
#ifdef RE_RAYCOUNTER
void RE_merge_raycounter(RayCounter *dest, RayCounter *tmp)
void RE_RC_INFO(RayCounter *info)
{
int i;
for(i=0; i<3; i++) dest->casted[i] += tmp->casted[i];
for(i=0; i<3; i++) dest->hit [i] += tmp->hit [i];
dest->test_primitives += tmp->test_primitives;
dest->hit_primitives += tmp->hit_primitives;
dest->test_bb += tmp->test_bb;
dest->hit_bb += tmp->hit_bb;
printf("----------- Raycast counter --------\n");
printf("Rays total: %llu\n", info->raycast.test );
printf("Rays hit: %llu\n", info->raycast.hit );
printf("\n");
printf("BB tests: %llu\n", info->bb.test );
printf("BB hits: %llu\n", info->bb.hit );
printf("\n");
printf("Primitives tests: %llu\n", info->faces.test );
printf("Primitives hits: %llu\n", info->faces.hit );
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("\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");
}
void RE_RC_MERGE(RayCounter *dest, RayCounter *tmp)
{
dest->faces.test += tmp->faces.test;
dest->faces.hit += tmp->faces.hit;
dest->bb.test += tmp->bb.test;
dest->bb.hit += tmp->bb.hit;
dest->raycast.test += tmp->raycast.test;
dest->raycast.hit += tmp->raycast.hit;
dest->rayshadow_last_hit_optimization += tmp->rayshadow_last_hit_optimization;
}
#endif

View File

@@ -66,7 +66,7 @@ RayObject *RE_rayobject_blibvh_create(int size)
assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */
obj->rayobj.api = &bvh_api;
obj->bvh = BLI_bvhtree_new(size, FLT_EPSILON, 4, 6);
obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6);
INIT_MINMAX(obj->bb[0], obj->bb[1]);
return RayObject_unalignRayAPI((RayObject*) obj);

View File

@@ -70,6 +70,22 @@
extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
RayObject *RE_rayobject_tree_create(int type, int size)
{
if(type == R_RAYTRACE_TREE_BVH)
return RE_rayobject_bvh_create(size);
if(type == R_RAYTRACE_TREE_BIH)
return RE_rayobject_bih_create(size);
if(type == R_RAYTRACE_TREE_BLIBVH)
return RE_rayobject_blibvh_create(size);
return RE_rayobject_bvh_create(size);
}
#ifdef RE_RAYCOUNTER
RayCounter re_rc_counter[BLENDER_MAX_THREADS] = {};
#endif
#if 0
static int vlr_check_intersect(Isect *is, int ob, RayFace *face)
{
@@ -123,6 +139,16 @@ void freeraytree(Render *re)
obi->raytree = NULL;
}
}
#ifdef RE_RAYCOUNTER
{
RayCounter sum = {};
int i;
for(i=0; i<BLENDER_MAX_THREADS; i++)
RE_RC_MERGE(&sum, re_rc_counter+i);
RE_RC_INFO(&sum);
}
#endif
}
static int is_raytraceable_vlr(Render *re, VlakRen *vlr)
@@ -180,7 +206,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi)
if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE)
raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces );
else //if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_BVH)
raytree = obr->raytree = RE_rayobject_tree_create( faces );
raytree = obr->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, faces );
face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces");
obr->rayobi = obi;
@@ -240,7 +266,7 @@ static void makeraytree_hier(Render *re)
num_objects++;
//Create raytree
re->raytree = RE_rayobject_tree_create( num_objects );
re->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, num_objects );
for(obi=re->instancetable.first; obi; obi=obi->next)
if(is_raytraceable(re, obi))
@@ -292,7 +318,7 @@ static void makeraytree_single(Render *re)
if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE)
raytree = re->raytree = RE_rayobject_octree_create( re->r.ocres, faces );
else //if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH)
raytree = re->raytree = RE_rayobject_tree_create( faces );
raytree = re->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, faces );
face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces");
@@ -322,6 +348,17 @@ static void makeraytree_single(Render *re)
void makeraytree(Render *re)
{
#ifdef RE_RAYCOUNTER
if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE)
printf("Building single octree\n");
else if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH)
printf("Building single tree\n");
else if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE)
printf("Building tree of octrees\n");
else
printf("Building tree of trees\n");
#endif
if(ELEM(re->r.raystructure, R_RAYSTRUCTURE_SINGLE_BVH, R_RAYSTRUCTURE_SINGLE_OCTREE))
BENCH(makeraytree_single(re), tree_build);
else
@@ -563,6 +600,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo
isec.orig.ob = obi;
isec.orig.face = vlr;
RE_RC_INIT(isec, shi);
if(RE_rayobject_raycast(R.raytree, &isec)) {
float d= 1.0f;
@@ -1306,7 +1344,6 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr)
do_tra= ((shi->mat->mode & (MA_RAYTRANSP)) && shr->alpha!=1.0f);
do_mir= ((shi->mat->mode & MA_RAYMIRROR) && shi->ray_mirror!=0.0f);
/* raytrace mirror amd refract like to separate the spec color */
if(shi->combinedflag & SCE_PASS_SPEC)
@@ -1465,6 +1502,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;
RE_RC_INIT(isec, shi);
for(a=0; a<8*8; a++) {
@@ -1669,6 +1707,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac)
float dxyview[3], skyadded=0, div;
int aocolor;
RE_RC_INIT(isec, *shi);
isec.orig.ob = shi->obi;
isec.orig.face = shi->vlr;
isec.skip = RE_SKIP_VLR_NEIGHBOUR;
@@ -1802,6 +1841,7 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac)
float dxyview[3];
int j= -1, tot, actual=0, skyadded=0, aocolor, resol= R.wrld.aosamp;
RE_RC_INIT(isec, *shi);
isec.orig.ob = shi->obi;
isec.orig.face = shi->vlr;
isec.skip = RE_SKIP_VLR_NEIGHBOUR;
@@ -2238,6 +2278,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
int lampvec; /* indicates if lampco is a vector lamp */
/* setup isec */
RE_RC_INIT(isec, *shi);
if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA;
else isec.mode= RE_RAY_SHADOW;
@@ -2323,6 +2364,7 @@ static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float
assert(0);
/* setup isec */
RE_RC_INIT(isec, *shi);
isec.mode= RE_RAY_SHADOW_TRA;
if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1;

View File

@@ -521,6 +521,12 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
}
}
break;
case SCE_PASS_RAYHITS:
/* */
col= &shr->rayhits;
pixsize= 4;
break;
}
if(col) {
fp= rpass->rect + pixsize*offset;
@@ -597,6 +603,10 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult
fp= rpass->rect + offset;
*fp= shr->mist;
break;
case SCE_PASS_RAYHITS:
col= shr->rayhits;
pixsize= 4;
break;
}
if(col) {
fp= rpass->rect + pixsize*offset;

View File

@@ -142,6 +142,7 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
float alpha;
/* ------ main shading loop -------- */
memset(&shi->raycounter, 0, sizeof(shi->raycounter));
if(shi->mat->nodetree && shi->mat->use_nodes) {
ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
@@ -188,6 +189,16 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
/* add z */
shr->z= -shi->co[2];
/* RAYHITS */
if(1 || shi->passflag & SCE_PASS_RAYHITS)
{
shr->rayhits[0] = (float)shi->raycounter.faces.test;
shr->rayhits[1] = (float)shi->raycounter.bb.hit;
shr->rayhits[2] = 0.0;
shr->rayhits[3] = 1.0;
RE_RC_MERGE(&re_rc_counter[shi->thread], &shi->raycounter);
}
}
/* **************************************************************************** */