Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2009-11-30 21:42:13 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2009-11-30 21:42:13 +0300
commitafe475b55b24ffdac9b9401bc81e5522ab901c4c (patch)
tree7b95addeb347a8b17449096dbd4315eaa58d5d1a /source/blender/render
parent4a4fff5b213bbd32d5c43d9e0a664b428cd16389 (diff)
Approximate AO: Diffuse Bounce Hack
This brings back the single bounce indirect diffuse lighting for AAO, it's not integrated well but that will be tackled later as part of shading system refactor and subdivision changes. The caveats are the same as AAO, with one extra thing, the diffuse lighting is sampled once per face, so it will not be accurate unless faces are subdivided. I'm committing this now so we can start testing it for Durian, and since changes need to make it work properly are planned.
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h2
-rw-r--r--source/blender/render/intern/include/render_types.h3
-rw-r--r--source/blender/render/intern/source/occlusion.c221
-rw-r--r--source/blender/render/intern/source/shadeoutput.c1
-rw-r--r--source/blender/render/intern/source/strand.c6
5 files changed, 156 insertions, 77 deletions
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index b36163f57c0..2615be1440a 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -153,7 +153,7 @@ typedef struct ShadeInput
float dxstrand, dystrand;
/* AO is a pre-process now */
- float ao[3];
+ float ao[3], indirect[3];
int xs, ys; /* pixel to be rendered */
int mask; /* subsample mask */
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 48bf34d0696..d41851db5ff 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -398,7 +398,8 @@ typedef struct StrandSurface {
int (*face)[4];
float (*co)[3];
/* for occlusion caching */
- float (*col)[3];
+ float (*ao)[3];
+ float (*indirect)[3];
/* for speedvectors */
float (*prevco)[3], (*nextco)[3];
int totvert, totface;
diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c
index f62668b84c0..90929db2f74 100644
--- a/source/blender/render/intern/source/occlusion.c
+++ b/source/blender/render/intern/source/occlusion.c
@@ -64,7 +64,7 @@
#define CACHE_STEP 3
typedef struct OcclusionCacheSample {
- float co[3], n[3], col[3], intensity, dist2;
+ float co[3], n[3], ao[3], indirect[3], intensity, dist2;
int x, y, filled;
} OcclusionCacheSample;
@@ -81,7 +81,7 @@ typedef struct OccFace {
typedef struct OccNode {
float co[3], area;
float sh[9], dco;
- float occlusion;
+ float occlusion, rad[3];
int childflag;
union {
//OccFace face;
@@ -97,6 +97,7 @@ typedef struct OcclusionTree {
OccFace *face; /* instance and face indices */
float *occlusion; /* occlusion for faces */
+ float (*rad)[3]; /* radiance for faces */
OccNode *root;
@@ -117,7 +118,8 @@ typedef struct OcclusionTree {
typedef struct OcclusionThread {
Render *re;
StrandSurface *mesh;
- float (*facecol)[3];
+ float (*faceao)[3];
+ float (*faceindirect)[3];
int begin, end;
int thread;
} OcclusionThread;
@@ -132,7 +134,6 @@ typedef struct OcclusionBuildThread {
extern Render R; // meh
-#if 0
static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, float *rad)
{
ShadeInput *shi= ssamp->shi;
@@ -160,7 +161,7 @@ static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr,
shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0];
shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1];
shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2];
-
+
shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
/* set up view vector */
@@ -179,6 +180,8 @@ static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr,
if(shi->flippednor)
shade_input_flip_normals(shi);
+ madd_v3_v3fl(shi->co, shi->vn, 0.0001f); /* ugly.. */
+
/* not a pretty solution, but fixes common cases */
if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) {
negate_v3(shi->vn);
@@ -215,12 +218,11 @@ static void occ_build_shade(Render *re, OcclusionTree *tree)
for(a=0; a<tree->totface; a++) {
obi= &R.objectinstance[tree->face[a].obi];
- vlr= RE_findOrAddVlak(obi->obr, tree->face[a].vlr);
+ vlr= RE_findOrAddVlak(obi->obr, tree->face[a].facenr);
occ_shade(&ssamp, obi, vlr, tree->rad[a]);
}
}
-#endif
/* ------------------------- Spherical Harmonics --------------------------- */
@@ -352,17 +354,19 @@ static void occ_face(const OccFace *face, float *co, float *normal, float *area)
static void occ_sum_occlusion(OcclusionTree *tree, OccNode *node)
{
OccNode *child;
- float occ, area, totarea;
+ float occ, area, totarea, rad[3];
int a, b;
occ= 0.0f;
totarea= 0.0f;
+ zero_v3(rad);
for(b=0; b<TOTCHILD; b++) {
if(node->childflag & (1<<b)) {
a= node->child[b].face;
occ_face(&tree->face[a], 0, 0, &area);
occ += area*tree->occlusion[a];
+ madd_v3_v3fl(rad, tree->rad[a], area);
totarea += area;
}
else if(node->child[b].node) {
@@ -370,14 +374,18 @@ static void occ_sum_occlusion(OcclusionTree *tree, OccNode *node)
occ_sum_occlusion(tree, child);
occ += child->area*child->occlusion;
+ madd_v3_v3fl(rad, child->rad, child->area);
totarea += child->area;
}
}
- if(totarea != 0.0f)
+ if(totarea != 0.0f) {
occ /= totarea;
+ mul_v3_fl(rad, 1.0f/totarea);
+ }
node->occlusion= occ;
+ copy_v3_v3(node->rad, rad);
}
static int occ_find_bbox_axis(OcclusionTree *tree, int begin, int end, float *min, float *max)
@@ -656,6 +664,9 @@ static OcclusionTree *occ_tree_build(Render *re)
tree->co= MEM_callocN(sizeof(float)*3*totface, "OcclusionCo");
tree->occlusion= MEM_callocN(sizeof(float)*totface, "OcclusionOcclusion");
+ if(re->wrld.ao_indirect_energy != 0.0f)
+ tree->rad= MEM_callocN(sizeof(float)*3*totface, "OcclusionRad");
+
/* make array of face pointers */
for(b=0, c=0, obi=re->instancetable.first; obi; obi=obi->next, c++) {
obr= obi->obr;
@@ -682,12 +693,10 @@ static OcclusionTree *occ_tree_build(Render *re)
tree->maxdepth= 1;
occ_build_recursive(tree, tree->root, 0, totface, 1);
-#if 0
- if(tree->doindirect) {
+ if(re->wrld.ao_indirect_energy != 0.0f) {
occ_build_shade(re, tree);
occ_sum_occlusion(tree, tree->root);
}
-#endif
MEM_freeN(tree->co);
tree->co= NULL;
@@ -710,8 +719,9 @@ static void occ_free_tree(OcclusionTree *tree)
if(tree->stack[a])
MEM_freeN(tree->stack[a]);
if(tree->occlusion) MEM_freeN(tree->occlusion);
- if(tree->face) MEM_freeN(tree->face);
if(tree->cache) MEM_freeN(tree->cache);
+ if(tree->face) MEM_freeN(tree->face);
+ if(tree->rad) MEM_freeN(tree->rad);
MEM_freeN(tree);
}
}
@@ -1171,13 +1181,13 @@ static float occ_form_factor(OccFace *face, float *p, float *n)
return contrib;
}
-static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float *pp, float *pn, float *occ, float *bentn)
+static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float *pp, float *pn, float *occ, float rad[3], float bentn[3])
{
OccNode *node, **stack;
OccFace *face;
- float resultocc, v[3], p[3], n[3], co[3], invd2;
+ float resultocc, resultrad[3], v[3], p[3], n[3], co[3], invd2;
float distfac, fac, error, d2, weight, emitarea;
- int b, totstack;
+ int b, f, totstack;
/* init variables */
VECCOPY(p, pp);
@@ -1185,12 +1195,13 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float
VECADDFAC(p, p, n, 1e-4f);
if(bentn)
- VECCOPY(bentn, n);
+ copy_v3_v3(bentn, n);
error= tree->error;
distfac= tree->distfac;
resultocc= 0.0f;
+ zero_v3(resultrad);
/* init stack */
stack= tree->stack[thread];
@@ -1217,6 +1228,10 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float
/* accumulate occlusion from spherical harmonics */
invd2 = 1.0f/sqrtf(d2);
weight= occ_solid_angle(node, v, d2, invd2, n);
+
+ if(rad)
+ madd_v3_v3fl(resultrad, node->rad, weight*fac);
+
weight *= node->occlusion;
if(bentn) {
@@ -1231,7 +1246,8 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float
/* traverse into children */
for(b=0; b<TOTCHILD; b++) {
if(node->childflag & (1<<b)) {
- face= tree->face+node->child[b].face;
+ f= node->child[b].face;
+ face= &tree->face[f];
/* accumulate occlusion with face form factor */
if(!exclude || !(face->obi == exclude->obi && face->facenr == exclude->facenr)) {
@@ -1248,7 +1264,11 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float
fac= 1.0f;
weight= occ_form_factor(face, p, n);
- weight *= tree->occlusion[node->child[b].face];
+
+ if(rad)
+ madd_v3_v3fl(resultrad, tree->rad[f], weight*fac);
+
+ weight *= tree->occlusion[f];
if(bentn) {
invd2= 1.0f/sqrtf(d2);
@@ -1269,15 +1289,24 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float
}
if(occ) *occ= resultocc;
+ if(rad) copy_v3_v3(rad, resultrad);
+ /*if(rad && exclude) {
+ int a;
+ for(a=0; a<tree->totface; a++)
+ if((tree->face[a].obi == exclude->obi && tree->face[a].facenr == exclude->facenr))
+ copy_v3_v3(rad, tree->rad[a]);
+ }*/
if(bentn) normalize_v3(bentn);
}
static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass)
{
- float *occ, co[3], n[3];
+ float *occ, (*rad)[3]= NULL, co[3], n[3];
int pass, i;
occ= MEM_callocN(sizeof(float)*tree->totface, "OcclusionPassOcc");
+ if(tree->rad)
+ rad= MEM_callocN(sizeof(float)*3*tree->totface, "OcclusionPassRad");
for(pass=0; pass<totpass; pass++) {
for(i=0; i<tree->totface; i++) {
@@ -1285,7 +1314,7 @@ static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass)
negate_v3(n);
VECADDFAC(co, co, n, 1e-8f);
- occ_lookup(tree, 0, &tree->face[i], co, n, &occ[i], NULL);
+ occ_lookup(tree, 0, &tree->face[i], co, n, &occ[i], NULL, (rad)? rad[i]: NULL);
if(re->test_break(re->tbh))
break;
}
@@ -1297,27 +1326,41 @@ static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass)
tree->occlusion[i] -= occ[i]; //MAX2(1.0f-occ[i], 0.0f);
if(tree->occlusion[i] < 0.0f)
tree->occlusion[i]= 0.0f;
+
+ if(rad) {
+ sub_v3_v3(tree->rad[i], rad[i]);
+
+ if(tree->rad[i][0] < 0.0f)
+ tree->rad[i][0]= 0.0f;
+ if(tree->rad[i][1] < 0.0f)
+ tree->rad[i][1]= 0.0f;
+ if(tree->rad[i][2] < 0.0f)
+ tree->rad[i][2]= 0.0f;
+ }
}
occ_sum_occlusion(tree, tree->root);
}
MEM_freeN(occ);
+ if(rad)
+ MEM_freeN(rad);
}
-static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, float *co, float *n, int thread, int onlyshadow, float *skycol)
+static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, float *co, float *n, int thread, int onlyshadow, float *ao, float *indirect)
{
- float nn[3], bn[3], fac, occ, occlusion, correction;
- int aocolor;
+ float nn[3], bn[3], fac, occ, occlusion, correction, rad[3];
+ int aocolor, aorad;
aocolor= re->wrld.aocolor;
if(onlyshadow)
aocolor= WO_AOPLAIN;
+ aorad= (re->wrld.ao_indirect_energy != 0.0f);
VECCOPY(nn, n);
negate_v3(nn);
- occ_lookup(tree, thread, exclude, co, nn, &occ, (aocolor)? bn: NULL);
+ occ_lookup(tree, thread, exclude, co, nn, &occ, (aorad)? rad: NULL, (aocolor)? bn: NULL);
correction= re->wrld.ao_approx_correction;
@@ -1330,9 +1373,9 @@ static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, f
/* sky shading using bent normal */
if(ELEM(aocolor, WO_AOSKYCOL, WO_AOSKYTEX)) {
fac= 0.5*(1.0f+bn[0]*re->grvec[0]+ bn[1]*re->grvec[1]+ bn[2]*re->grvec[2]);
- skycol[0]= (1.0f-fac)*re->wrld.horr + fac*re->wrld.zenr;
- skycol[1]= (1.0f-fac)*re->wrld.horg + fac*re->wrld.zeng;
- skycol[2]= (1.0f-fac)*re->wrld.horb + fac*re->wrld.zenb;
+ ao[0]= (1.0f-fac)*re->wrld.horr + fac*re->wrld.zenr;
+ ao[1]= (1.0f-fac)*re->wrld.horg + fac*re->wrld.zeng;
+ ao[2]= (1.0f-fac)*re->wrld.horb + fac*re->wrld.zenb;
}
#if 0
else { /* WO_AOSKYTEX */
@@ -1343,17 +1386,20 @@ static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, f
dxyview[0]= 1.0f;
dxyview[1]= 1.0f;
dxyview[2]= 0.0f;
- shadeSkyView(skycol, co, bn, dxyview);
+ shadeSkyView(ao, co, bn, dxyview);
}
#endif
- mul_v3_fl(skycol, occlusion);
+ mul_v3_fl(ao, occlusion);
}
else {
- skycol[0]= occlusion;
- skycol[1]= occlusion;
- skycol[2]= occlusion;
+ ao[0]= occlusion;
+ ao[1]= occlusion;
+ ao[2]= occlusion;
}
+
+ if(aorad) copy_v3_v3(indirect, rad);
+ else zero_v3(indirect);
}
/* ---------------------------- Caching ------------------------------- */
@@ -1374,7 +1420,7 @@ static OcclusionCacheSample *find_occ_sample(OcclusionCache *cache, int x, int y
return &cache->sample[y*cache->w + x];
}
-static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int y, int thread, float *col)
+static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int y, int thread, float *ao, float *indirect)
{
OcclusionCache *cache;
OcclusionCacheSample *samples[4], *sample;
@@ -1394,7 +1440,8 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int
VECSUB(d, sample->co, co);
dist2= INPR(d, d);
if(dist2 < 0.5f*sample->dist2 && INPR(sample->n, n) > 0.98f) {
- VECCOPY(col, sample->col);
+ VECCOPY(ao, sample->ao);
+ VECCOPY(indirect, sample->indirect);
return 1;
}
}
@@ -1420,7 +1467,8 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int
return 0;
/* compute weighted interpolation between samples */
- col[0]= col[1]= col[2]= 0.0f;
+ zero_v3(ao);
+ zero_v3(indirect);
totw= 0.0f;
x1= samples[0]->x;
@@ -1446,16 +1494,14 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int
w= wb[i]*wn[i]*wz[i];
totw += w;
- col[0] += w*samples[i]->col[0];
- col[1] += w*samples[i]->col[1];
- col[2] += w*samples[i]->col[2];
+ madd_v3_v3fl(ao, samples[i]->ao, w);
+ madd_v3_v3fl(indirect, samples[i]->indirect, w);
}
if(totw >= 0.9f) {
totw= 1.0f/totw;
- col[0] *= totw;
- col[1] *= totw;
- col[2] *= totw;
+ mul_v3_fl(ao, totw);
+ mul_v3_fl(indirect, totw);
return 1;
}
@@ -1469,7 +1515,7 @@ static void sample_occ_surface(ShadeInput *shi)
int *face, *index = RE_strandren_get_face(shi->obr, strand, 0);
float w[4], *co1, *co2, *co3, *co4;
- if(mesh && mesh->face && mesh->co && mesh->col && index) {
+ if(mesh && mesh->face && mesh->co && mesh->ao && index) {
face= mesh->face[*index];
co1= mesh->co[face[0]];
@@ -1477,19 +1523,27 @@ static void sample_occ_surface(ShadeInput *shi)
co3= mesh->co[face[2]];
co4= (face[3])? mesh->co[face[3]]: NULL;
- interp_weights_face_v3( w,co1, co2, co3, co4, strand->vert->co);
+ interp_weights_face_v3(w, co1, co2, co3, co4, strand->vert->co);
+
+ zero_v3(shi->ao);
+ zero_v3(shi->indirect);
- shi->ao[0]= shi->ao[1]= shi->ao[2]= 0.0f;
- VECADDFAC(shi->ao, shi->ao, mesh->col[face[0]], w[0]);
- VECADDFAC(shi->ao, shi->ao, mesh->col[face[1]], w[1]);
- VECADDFAC(shi->ao, shi->ao, mesh->col[face[2]], w[2]);
- if(face[3])
- VECADDFAC(shi->ao, shi->ao, mesh->col[face[3]], w[3]);
+ madd_v3_v3fl(shi->ao, mesh->ao[face[0]], w[0]);
+ madd_v3_v3fl(shi->indirect, mesh->indirect[face[0]], w[0]);
+ madd_v3_v3fl(shi->ao, mesh->ao[face[1]], w[1]);
+ madd_v3_v3fl(shi->indirect, mesh->indirect[face[1]], w[1]);
+ madd_v3_v3fl(shi->ao, mesh->ao[face[2]], w[2]);
+ madd_v3_v3fl(shi->indirect, mesh->indirect[face[2]], w[2]);
+ if(face[3]) {
+ madd_v3_v3fl(shi->ao, mesh->ao[face[3]], w[3]);
+ madd_v3_v3fl(shi->indirect, mesh->indirect[face[3]], w[3]);
+ }
}
else {
shi->ao[0]= 1.0f;
shi->ao[1]= 1.0f;
shi->ao[2]= 1.0f;
+ zero_v3(shi->indirect);
}
}
@@ -1500,7 +1554,7 @@ static void *exec_strandsurface_sample(void *data)
OcclusionThread *othread= (OcclusionThread*)data;
Render *re= othread->re;
StrandSurface *mesh= othread->mesh;
- float col[3], co[3], n[3], *co1, *co2, *co3, *co4;
+ float ao[3], indirect[3], co[3], n[3], *co1, *co2, *co3, *co4;
int a, *face;
for(a=othread->begin; a<othread->end; a++) {
@@ -1521,8 +1575,9 @@ static void *exec_strandsurface_sample(void *data)
}
negate_v3(n);
- sample_occ_tree(re, re->occlusiontree, NULL, co, n, othread->thread, 0, col);
- VECCOPY(othread->facecol[a], col);
+ sample_occ_tree(re, re->occlusiontree, NULL, co, n, othread->thread, 0, ao, indirect);
+ VECCOPY(othread->faceao[a], ao);
+ VECCOPY(othread->faceindirect[a], indirect);
}
return 0;
@@ -1533,7 +1588,7 @@ void make_occ_tree(Render *re)
OcclusionThread othreads[BLENDER_MAX_THREADS];
StrandSurface *mesh;
ListBase threads;
- float col[3], (*facecol)[3];
+ float ao[3], indirect[3], (*faceao)[3], (*faceindirect)[3];
int a, totface, totthread, *face, *count;
/* ugly, needed for occ_face */
@@ -1549,17 +1604,19 @@ void make_occ_tree(Render *re)
occ_compute_passes(re, re->occlusiontree, re->wrld.ao_approx_passes);
for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) {
- if(!mesh->face || !mesh->co || !mesh->col)
+ if(!mesh->face || !mesh->co || !mesh->ao)
continue;
count= MEM_callocN(sizeof(int)*mesh->totvert, "OcclusionCount");
- facecol= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceCol");
+ faceao= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceAO");
+ faceindirect= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceIndirect");
totthread= (mesh->totface > 10000)? re->r.threads: 1;
totface= mesh->totface/totthread;
for(a=0; a<totthread; a++) {
othreads[a].re= re;
- othreads[a].facecol= facecol;
+ othreads[a].faceao= faceao;
+ othreads[a].faceindirect= faceindirect;
othreads[a].thread= a;
othreads[a].mesh= mesh;
othreads[a].begin= a*totface;
@@ -1581,26 +1638,36 @@ void make_occ_tree(Render *re)
for(a=0; a<mesh->totface; a++) {
face= mesh->face[a];
- VECCOPY(col, facecol[a]);
- VECADD(mesh->col[face[0]], mesh->col[face[0]], col);
+ VECCOPY(ao, faceao[a]);
+ VECCOPY(indirect, faceindirect[a]);
+
+ VECADD(mesh->ao[face[0]], mesh->ao[face[0]], ao);
+ VECADD(mesh->indirect[face[0]], mesh->indirect[face[0]], indirect);
count[face[0]]++;
- VECADD(mesh->col[face[1]], mesh->col[face[1]], col);
+ VECADD(mesh->ao[face[1]], mesh->ao[face[1]], ao);
+ VECADD(mesh->indirect[face[1]], mesh->indirect[face[1]], indirect);
count[face[1]]++;
- VECADD(mesh->col[face[2]], mesh->col[face[2]], col);
+ VECADD(mesh->ao[face[2]], mesh->ao[face[2]], ao);
+ VECADD(mesh->indirect[face[2]], mesh->indirect[face[2]], indirect);
count[face[2]]++;
if(face[3]) {
- VECADD(mesh->col[face[3]], mesh->col[face[3]], col);
+ VECADD(mesh->ao[face[3]], mesh->ao[face[3]], ao);
+ VECADD(mesh->indirect[face[3]], mesh->indirect[face[3]], indirect);
count[face[3]]++;
}
}
- for(a=0; a<mesh->totvert; a++)
- if(count[a])
- mul_v3_fl(mesh->col[a], 1.0f/count[a]);
+ for(a=0; a<mesh->totvert; a++) {
+ if(count[a]) {
+ mul_v3_fl(mesh->ao[a], 1.0f/count[a]);
+ mul_v3_fl(mesh->indirect[a], 1.0f/count[a]);
+ }
+ }
MEM_freeN(count);
- MEM_freeN(facecol);
+ MEM_freeN(faceao);
+ MEM_freeN(faceindirect);
}
}
}
@@ -1626,12 +1693,12 @@ void sample_occ(Render *re, ShadeInput *shi)
sample_occ_surface(shi);
}
/* try to get result from the cache if possible */
- else if(shi->depth!=0 || !sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao)) {
+ else if(shi->depth!=0 || !sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao, shi->indirect)) {
/* no luck, let's sample the occlusion */
exclude.obi= shi->obi - re->objectinstance;
exclude.facenr= shi->vlr->index;
onlyshadow= (shi->mat->mode & MA_ONLYSHADOW);
- sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao);
+ sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao, shi->indirect);
/* fill result into sample, each time */
if(tree->cache) {
@@ -1641,8 +1708,10 @@ void sample_occ(Render *re, ShadeInput *shi)
sample= &cache->sample[(shi->ys-cache->y)*cache->w + (shi->xs-cache->x)];
VECCOPY(sample->co, shi->co);
VECCOPY(sample->n, shi->vno);
- VECCOPY(sample->col, shi->ao);
- sample->intensity= MAX3(sample->col[0], sample->col[1], sample->col[2]);
+ VECCOPY(sample->ao, shi->ao);
+ VECCOPY(sample->indirect, shi->indirect);
+ sample->intensity= MAX3(sample->ao[0], sample->ao[1], sample->ao[2]);
+ sample->intensity= MAX2(sample->intensity, MAX3(sample->indirect[0], sample->indirect[1], sample->indirect[2]));
sample->dist2= INPR(shi->dxco, shi->dxco) + INPR(shi->dyco, shi->dyco);
sample->filled= 1;
}
@@ -1653,6 +1722,10 @@ void sample_occ(Render *re, ShadeInput *shi)
shi->ao[0]= 1.0f;
shi->ao[1]= 1.0f;
shi->ao[2]= 1.0f;
+
+ shi->indirect[0]= 0.0f;
+ shi->indirect[1]= 0.0f;
+ shi->indirect[2]= 0.0f;
}
}
@@ -1720,12 +1793,14 @@ void cache_occ_samples(Render *re, RenderPart *pa, ShadeSample *ssamp)
onlyshadow= (shi->mat->mode & MA_ONLYSHADOW);
exclude.obi= shi->obi - re->objectinstance;
exclude.facenr= shi->vlr->index;
- sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao);
+ sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao, shi->indirect);
VECCOPY(sample->co, shi->co);
VECCOPY(sample->n, shi->vno);
- VECCOPY(sample->col, shi->ao);
- sample->intensity= MAX3(sample->col[0], sample->col[1], sample->col[2]);
+ VECCOPY(sample->ao, shi->ao);
+ VECCOPY(sample->indirect, shi->indirect);
+ sample->intensity= MAX3(sample->ao[0], sample->ao[1], sample->ao[2]);
+ sample->intensity= MAX2(sample->intensity, MAX3(sample->indirect[0], sample->indirect[1], sample->indirect[2]));
sample->dist2= INPR(shi->dxco, shi->dxco) + INPR(shi->dyco, shi->dyco);
sample->x= shi->xs;
sample->y= shi->ys;
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index f167122f497..958a2e34215 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -1041,6 +1041,7 @@ void ambient_occlusion_to_diffuse(ShadeInput *shi, float *diff)
}
VECMUL(diff, f);
+ madd_v3_v3fl(diff, shi->indirect, R.wrld.ao_indirect_energy*shi->amb);
}
else
diff[0]= diff[1]= diff[2]= 0.0f;
diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c
index 47a7c052b18..ecea7360974 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -959,7 +959,8 @@ StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm,
mesh->totvert= totvert;
mesh->totface= totface;
mesh->face= MEM_callocN(sizeof(int)*4*mesh->totface, "StrandSurfFaces");
- mesh->col= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfCol");
+ mesh->ao= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfAO");
+ mesh->indirect= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfIndirect");
BLI_addtail(&re->strandsurface, mesh);
}
@@ -997,7 +998,8 @@ void free_strand_surface(Render *re)
if(mesh->co) MEM_freeN(mesh->co);
if(mesh->prevco) MEM_freeN(mesh->prevco);
if(mesh->nextco) MEM_freeN(mesh->nextco);
- if(mesh->col) MEM_freeN(mesh->col);
+ if(mesh->ao) MEM_freeN(mesh->ao);
+ if(mesh->indirect) MEM_freeN(mesh->indirect);
if(mesh->face) MEM_freeN(mesh->face);
}