diff options
Diffstat (limited to 'source/blender/render/intern')
-rw-r--r-- | source/blender/render/intern/include/render_types.h | 4 | ||||
-rw-r--r-- | source/blender/render/intern/include/volume_precache.h | 2 | ||||
-rw-r--r-- | source/blender/render/intern/include/volumetric.h | 3 | ||||
-rw-r--r-- | source/blender/render/intern/source/convertblender.c | 61 | ||||
-rw-r--r-- | source/blender/render/intern/source/pipeline.c | 172 | ||||
-rw-r--r-- | source/blender/render/intern/source/pointdensity.c | 5 | ||||
-rw-r--r-- | source/blender/render/intern/source/rayshade.c | 6 | ||||
-rw-r--r-- | source/blender/render/intern/source/renderdatabase.c | 10 | ||||
-rw-r--r-- | source/blender/render/intern/source/sss.c | 17 | ||||
-rw-r--r-- | source/blender/render/intern/source/texture.c | 121 | ||||
-rw-r--r-- | source/blender/render/intern/source/volume_precache.c | 53 | ||||
-rw-r--r-- | source/blender/render/intern/source/volumetric.c | 286 | ||||
-rw-r--r-- | source/blender/render/intern/source/voxeldata.c | 14 |
13 files changed, 463 insertions, 291 deletions
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index e50e498228d..96306be31c8 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -121,6 +121,10 @@ struct Render RenderResult *pushedresult; /* a list of RenderResults, for fullsample */ ListBase fullresult; + /* read/write mutex, all internal code that writes to re->result must use a + write lock, all external code must use a read lock. internal code is assumed + to not conflict with writes, so no lock used for that */ + ThreadRWMutex resultmutex; /* window size, display rect, viewplane */ int winx, winy; diff --git a/source/blender/render/intern/include/volume_precache.h b/source/blender/render/intern/include/volume_precache.h index 9d87a219c82..368d60ee7f0 100644 --- a/source/blender/render/intern/include/volume_precache.h +++ b/source/blender/render/intern/include/volume_precache.h @@ -30,4 +30,4 @@ void volume_precache(Render *re); void free_volume_precache(Render *re); int point_inside_volume_objectinstance(ObjectInstanceRen *obi, float *co); -#define VOL_MS_TIMESTEP 0.1f
\ No newline at end of file +#define VOL_MS_TIMESTEP 0.1f diff --git a/source/blender/render/intern/include/volumetric.h b/source/blender/render/intern/include/volumetric.h index 026b4840ea3..97e7e022fa0 100644 --- a/source/blender/render/intern/include/volumetric.h +++ b/source/blender/render/intern/include/volumetric.h @@ -26,9 +26,8 @@ * ***** END GPL LICENSE BLOCK ***** */ -float vol_get_stepsize(struct ShadeInput *shi, int context); float vol_get_density(struct ShadeInput *shi, float *co); -void vol_get_scattering(ShadeInput *shi, float *scatter_col, float *co, float stepsize, float density); +void vol_get_scattering(ShadeInput *shi, float *scatter_col, float *co_); void shade_volume_outside(ShadeInput *shi, ShadeResult *shr); void shade_volume_inside(ShadeInput *shi, ShadeResult *shr); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 99825c0c2ff..b3784f26048 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -889,6 +889,28 @@ static void free_mesh_orco_hash(Render *re) } } +static void check_material_mapto(Material *ma) +{ + int a; + ma->mapto_textured = 0; + + /* cache which inputs are actually textured. + * this can avoid a bit of time spent iterating through all the texture slots, map inputs and map tos + * every time a property which may or may not be textured is accessed */ + + for(a=0; a<MAX_MTEX; a++) { + if(ma->mtex[a] && ma->mtex[a]->tex) { + /* currently used only in volume render, so we'll check for those flags */ + if(ma->mtex[a]->mapto & MAP_DENSITY) ma->mapto_textured |= MAP_DENSITY; + if(ma->mtex[a]->mapto & MAP_EMISSION) ma->mapto_textured |= MAP_EMISSION; + if(ma->mtex[a]->mapto & MAP_EMISSION_COL) ma->mapto_textured |= MAP_EMISSION_COL; + if(ma->mtex[a]->mapto & MAP_SCATTERING) ma->mapto_textured |= MAP_SCATTERING; + if(ma->mtex[a]->mapto & MAP_TRANSMISSION_COL) ma->mapto_textured |= MAP_TRANSMISSION_COL; + if(ma->mtex[a]->mapto & MAP_REFLECTION) ma->mapto_textured |= MAP_REFLECTION; + if(ma->mtex[a]->mapto & MAP_REFLECTION_COL) ma->mapto_textured |= MAP_REFLECTION_COL; + } + } +} static void flag_render_node_material(Render *re, bNodeTree *ntree) { bNode *node; @@ -930,6 +952,8 @@ static Material *give_render_material(Render *re, Object *ob, int nr) if(ma->nodetree && ma->use_nodes) flag_render_node_material(re, ma->nodetree); + check_material_mapto(ma); + return ma; } @@ -1474,7 +1498,7 @@ static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset) { Object *ob= obr->ob; - Object *tob=0; +// Object *tob=0; Material *ma=0; ParticleSystemModifierData *psmd; ParticleSystem *tpsys=0; @@ -1484,6 +1508,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem ParticleKey state; ParticleCacheKey *cache=0; ParticleBillboardData bb; + ParticleSimulationData sim = {re->scene, ob, psys, NULL}; ParticleStrandData sd; StrandBuffer *strandbuf=0; StrandVert *svert=0; @@ -1517,14 +1542,16 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem return 1; /* 2. start initialising things */ - if(part->phystype==PART_PHYS_KEYED) - psys_count_keyed_targets(ob,psys); /* last possibility to bail out! */ - psmd= psys_get_modifier(ob,psys); + sim.psmd = psmd = psys_get_modifier(ob,psys); if(!(psmd->modifier.mode & eModifierMode_Render)) return 0; + if(part->phystype==PART_PHYS_KEYED) + psys_count_keyed_targets(&sim); + + if(G.rendering == 0) { /* preview render */ totchild = (int)((float)totchild * (float)part->disp / 100.0f); } @@ -1611,14 +1638,14 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem #endif // XXX old animation system cfra = bsystem_time(re->scene, 0, (float)re->scene->r.cfra, 0.0); -/* 2.4 setup reactors */ - if(part->type == PART_REACTOR){ - psys_get_reactor_target(ob, psys, &tob, &tpsys); - if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){ - psmd = psys_get_modifier(tob,tpsys); - tpart = tpsys->part; - } - } +///* 2.4 setup reactors */ +// if(part->type == PART_REACTOR){ +// psys_get_reactor_target(ob, psys, &tob, &tpsys); +// if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){ +// psmd = psys_get_modifier(tob,tpsys); +// tpart = tpsys->part; +// } +// } /* 2.5 setup matrices */ Mat4MulMat4(mat, ob->obmat, re->viewmat); @@ -1695,7 +1722,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem } if(path_nbr == 0) - psys->lattice = psys_get_lattice(re->scene, ob, psys); + psys->lattice = psys_get_lattice(&sim); /* 3. start creating renderable things */ for(a=0,pa=pars; a<totpart+totchild; a++, pa++, seed++) { @@ -1786,8 +1813,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem pa_size = psys_get_child_size(psys, cpa, cfra, &pa_time); - r_tilt = 2.0f * cpa->rand[2]; - r_length = cpa->rand[1]; + r_tilt = 2.0f*(PSYS_FRAND(a + 21) - 0.5f); + r_length = PSYS_FRAND(a + 22); num = cpa->num; @@ -1952,7 +1979,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem continue; state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : ct; - psys_get_particle_on_path(re->scene,ob,psys,a,&state,1); + psys_get_particle_on_path(&sim,a,&state,1); if(psys->parent) Mat4MulVecfl(psys->parent->obmat, state.co); @@ -1971,7 +1998,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem else { time=0.0f; state.time=cfra; - if(psys_get_particle_state(re->scene,ob,psys,a,&state,0)==0) + if(psys_get_particle_state(&sim,a,&state,0)==0) continue; if(psys->parent) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index a6b089c6029..077f826b1ef 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -213,11 +213,15 @@ static void free_render_result(ListBase *lb, RenderResult *rr) /* all layers except the active one get temporally pushed away */ static void push_render_result(Render *re) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + /* officially pushed result should be NULL... error can happen with do_seq */ RE_FreeRenderResult(re->pushedresult); re->pushedresult= re->result; re->result= NULL; + + BLI_rw_mutex_unlock(&re->resultmutex); } /* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */ @@ -229,6 +233,8 @@ static void pop_render_result(Render *re) return; } if(re->pushedresult) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + if(re->pushedresult->rectx==re->result->rectx && re->pushedresult->recty==re->result->recty) { /* find which layer in pushedresult should be replaced */ SceneRenderLayer *srl; @@ -255,6 +261,8 @@ static void pop_render_result(Render *re) RE_FreeRenderResult(re->pushedresult); re->pushedresult= NULL; + + BLI_rw_mutex_unlock(&re->resultmutex); } } @@ -406,7 +414,7 @@ static int passtype_from_name(char *str) static void render_unique_exr_name(Render *re, char *str, int sample) { - char di[FILE_MAX], name[FILE_MAXFILE], fi[FILE_MAXFILE]; + char di[FILE_MAX], name[FILE_MAXFILE+MAX_ID_NAME+100], fi[FILE_MAXFILE]; BLI_strncpy(di, G.sce, FILE_MAX); BLI_splitdirstring(di, fi); @@ -920,6 +928,8 @@ static void read_render_result(Render *re, int sample) { char str[FILE_MAX]; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + RE_FreeRenderResult(re->result); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); @@ -928,6 +938,8 @@ static void read_render_result(Render *re, int sample) if(!read_render_result_from_file(str, re->result)) printf("cannot read: %s\n", str); + + BLI_rw_mutex_unlock(&re->resultmutex); } /* *************************************************** */ @@ -946,13 +958,32 @@ Render *RE_GetRender(const char *name) } /* if you want to know exactly what has been done */ -RenderResult *RE_GetResult(Render *re) +RenderResult *RE_AcquireResultRead(Render *re) { - if(re) + if(re) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ); return re->result; + } + return NULL; } +RenderResult *RE_AcquireResultWrite(Render *re) +{ + if(re) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + return re->result; + } + + return NULL; +} + +void RE_ReleaseResult(Render *re) +{ + if(re) + BLI_rw_mutex_unlock(&re->resultmutex); +} + /* displist.c util.... */ Scene *RE_GetScene(Render *re) { @@ -973,38 +1004,49 @@ RenderLayer *render_get_active_layer(Render *re, RenderResult *rr) /* fill provided result struct with what's currently active or done */ -void RE_GetResultImage(Render *re, RenderResult *rr) +void RE_AcquireResultImage(Render *re, RenderResult *rr) { memset(rr, 0, sizeof(RenderResult)); - if(re && re->result) { - RenderLayer *rl; - - rr->rectx= re->result->rectx; - rr->recty= re->result->recty; - - rr->rectf= re->result->rectf; - rr->rectz= re->result->rectz; - rr->rect32= re->result->rect32; - - /* active layer */ - rl= render_get_active_layer(re, re->result); + if(re) { + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_READ); - if(rl) { - if(rr->rectf==NULL) - rr->rectf= rl->rectf; - if(rr->rectz==NULL) - rr->rectz= RE_RenderLayerGetPass(rl, SCE_PASS_Z); + if(re->result) { + RenderLayer *rl; + + rr->rectx= re->result->rectx; + rr->recty= re->result->recty; + + rr->rectf= re->result->rectf; + rr->rectz= re->result->rectz; + rr->rect32= re->result->rect32; + + /* active layer */ + rl= render_get_active_layer(re, re->result); + + if(rl) { + if(rr->rectf==NULL) + rr->rectf= rl->rectf; + if(rr->rectz==NULL) + rr->rectz= RE_RenderLayerGetPass(rl, SCE_PASS_Z); + } } } } +void RE_ReleaseResultImage(Render *re) +{ + if(re) + BLI_rw_mutex_unlock(&re->resultmutex); +} + /* caller is responsible for allocating rect in correct size! */ void RE_ResultGet32(Render *re, unsigned int *rect) { RenderResult rres; - RE_GetResultImage(re, &rres); + RE_AcquireResultImage(re, &rres); + if(rres.rect32) memcpy(rect, rres.rect32, sizeof(int)*rres.rectx*rres.recty); else if(rres.rectf) { @@ -1022,6 +1064,8 @@ void RE_ResultGet32(Render *re, unsigned int *rect) else /* else fill with black */ memset(rect, 0, sizeof(int)*re->rectx*re->recty); + + RE_ReleaseResultImage(re); } @@ -1042,12 +1086,15 @@ Render *RE_NewRender(const char *name) re= MEM_callocN(sizeof(Render), "new render"); BLI_addtail(&RenderList, re); strncpy(re->name, name, RE_MAXNAME); + BLI_rw_mutex_init(&re->resultmutex); } /* prevent UI to draw old results */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); RE_FreeRenderResult(re->result); re->result= NULL; re->result_ok= 0; + BLI_rw_mutex_unlock(&re->resultmutex); /* set default empty callbacks */ re->display_init= result_nothing; @@ -1072,6 +1119,7 @@ Render *RE_NewRender(const char *name) /* only call this while you know it will remove the link too */ void RE_FreeRender(Render *re) { + BLI_rw_mutex_end(&re->resultmutex); free_renderdata_tables(re); free_sample_tables(re); @@ -1153,6 +1201,8 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, int winx, int winy make_sample_tables(re); /* if preview render, we try to keep old result */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + if(re->r.scemode & R_PREVIEWBUTS) { if(re->result && re->result->rectx==re->rectx && re->result->recty==re->recty); else { @@ -1168,6 +1218,8 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, int winx, int winy re->result->rectx= re->rectx; re->result->recty= re->recty; } + + BLI_rw_mutex_unlock(&re->resultmutex); /* we clip faces with a minimum of 2 pixel boundary outside of image border. see zbuf.c */ re->clipcrop= 1.0f + 2.0f/(float)(re->winx>re->winy?re->winy:re->winx); @@ -1184,8 +1236,12 @@ void RE_SetDispRect (struct Render *re, rcti *disprect) re->recty= disprect->ymax-disprect->ymin; /* initialize render result */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + RE_FreeRenderResult(re->result); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); + + BLI_rw_mutex_unlock(&re->resultmutex); } void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend) @@ -1345,11 +1401,15 @@ static void render_tile_processor(Render *re, int firsttile) if(re->test_break(re->tbh)) return; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + /* hrmf... exception, this is used for preview render, re-entrant, so render result has to be re-used */ if(re->result==NULL || re->result->layers.first==NULL) { if(re->result) RE_FreeRenderResult(re->result); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); } + + BLI_rw_mutex_unlock(&re->resultmutex); re->stats_draw(re->sdh, &re->i); @@ -1357,7 +1417,7 @@ static void render_tile_processor(Render *re, int firsttile) return; initparts(re); - + /* assuming no new data gets added to dbase... */ R= *re; @@ -1384,7 +1444,7 @@ static void render_tile_processor(Render *re, int firsttile) break; } } - + freeparts(re); } @@ -1522,17 +1582,21 @@ static void threaded_tile_processor(Render *re) rctf viewplane= re->viewplane; int rendering=1, counter= 1, drawtimer=0, hasdrawn, minx=0; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + /* first step; free the entire render result, make new, and/or prepare exr buffer saving */ if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) { RE_FreeRenderResult(re->result); - if(re->sss_points) + if(re->sss_points && render_display_draw_enabled(re)) re->result= new_render_result(re, &re->disprect, 0, 0); else if(re->r.scemode & R_FULL_SAMPLE) re->result= new_full_sample_buffers_exr(re); else re->result= new_render_result(re, &re->disprect, 0, re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)); } + + BLI_rw_mutex_unlock(&re->resultmutex); if(re->result==NULL) return; @@ -1540,7 +1604,7 @@ static void threaded_tile_processor(Render *re) /* warning; no return here without closing exr file */ initparts(re); - + if(re->result->exrhandle) { RenderResult *rr; char str[FILE_MAX]; @@ -1629,6 +1693,8 @@ static void threaded_tile_processor(Render *re) } + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + if(re->result->exrhandle) { RenderResult *rr; @@ -1644,6 +1710,8 @@ static void threaded_tile_processor(Render *re) read_render_result(re, 0); } + + BLI_rw_mutex_unlock(&re->resultmutex); /* unset threadsafety */ g_break= 0; @@ -1823,8 +1891,10 @@ static void do_render_blur_3d(Render *re) } /* swap results */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); RE_FreeRenderResult(re->result); re->result= rres; + BLI_rw_mutex_unlock(&re->resultmutex); set_mblur_offs(0.0f); re->i.curblur= 0; /* stats */ @@ -1894,8 +1964,11 @@ static void do_render_fields_3d(Render *re) do_render_blur_3d(re); else do_render_3d(re); + + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); rr1= re->result; re->result= NULL; + BLI_rw_mutex_unlock(&re->resultmutex); /* second field */ if(!re->test_break(re->tbh)) { @@ -1921,8 +1994,11 @@ static void do_render_fields_3d(Render *re) re->recty *= 2; re->disprect.ymin *= 2; re->disprect.ymax *= 2; + + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); - + RE_FreeRenderResult(rr1); + if(rr2) { if(re->r.mode & R_ODDFIELD) merge_renderresult_fields(re->result, rr2, rr1); @@ -1931,12 +2007,14 @@ static void do_render_fields_3d(Render *re) RE_FreeRenderResult(rr2); } - RE_FreeRenderResult(rr1); re->i.curfield= 0; /* stats */ /* weak... the display callback wants an active renderlayer pointer... */ re->result->renlay= render_get_active_layer(re, re->result); + + BLI_rw_mutex_unlock(&re->resultmutex); + re->display_draw(re->ddh, re->result, NULL); } @@ -2000,6 +2078,8 @@ static void do_render_fields_blur_3d(Render *re) if((re->r.mode & R_CROP)==0) { RenderResult *rres; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + /* sub-rect for merge call later on */ re->result->tilerect= re->disprect; @@ -2020,6 +2100,8 @@ static void do_render_fields_blur_3d(Render *re) /* weak... the display callback wants an active renderlayer pointer... */ re->result->renlay= render_get_active_layer(re, re->result); + BLI_rw_mutex_unlock(&re->resultmutex); + re->display_init(re->dih, re->result); re->display_draw(re->ddh, re->result, NULL); } @@ -2176,7 +2258,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) } /* ensure we get either composited result or the active layer */ - RE_GetResultImage(re, &rres); + RE_AcquireResultImage(re, &rres); /* accumulate with filter, and clip */ mask= (1<<sample); @@ -2195,6 +2277,8 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) } } + RE_ReleaseResultImage(re); + /* show stuff */ if(sample!=re->osa-1) { /* weak... the display callback wants an active renderlayer pointer... */ @@ -2206,9 +2290,11 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) break; } + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if(re->result->rectf) MEM_freeN(re->result->rectf); re->result->rectf= rectf; + BLI_rw_mutex_unlock(&re->resultmutex); } void RE_MergeFullSample(Render *re, Scene *sce, bNodeTree *ntree) @@ -2309,9 +2395,12 @@ static void do_render_composite_fields_blur_3d(Render *re) static void renderresult_stampinfo(Scene *scene) { RenderResult rres; + Render *re= RE_GetRender(scene->id.name); + /* this is the basic trick to get the displayed float or char rect from render result */ - RE_GetResultImage(RE_GetRender(scene->id.name), &rres); + RE_AcquireResultImage(re, &rres); BKE_stamp_buf(scene, (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4); + RE_ReleaseResultImage(re); } static void do_render_seq(Render * re) @@ -2327,6 +2416,8 @@ static void do_render_seq(Render * re) recurs_depth--; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + if(ibuf) { if(ibuf->rect_float) { if (!rr->rectf) @@ -2369,6 +2460,8 @@ static void do_render_seq(Render * re) else rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect"); } + + BLI_rw_mutex_unlock(&re->resultmutex); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -2388,14 +2481,15 @@ static void do_render_all_options(Render *re) re->stats_draw(re->sdh, &re->i); re->display_draw(re->ddh, re->result, NULL); - } else { do_render_composite_fields_blur_3d(re); } /* for UI only */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); renderresult_add_names(re->result); + BLI_rw_mutex_unlock(&re->resultmutex); re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime; @@ -2622,7 +2716,7 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh) char name[FILE_MAX]; RenderResult rres; - RE_GetResultImage(re, &rres); + RE_AcquireResultImage(re, &rres); /* write movie or image */ if(BKE_imtype_is_movie(scene->r.imtype)) { @@ -2686,6 +2780,8 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh) } } + RE_ReleaseResultImage(re); + BLI_timestr(re->i.lastframetime, name); printf(" Time: %s\n", name); fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */ @@ -2723,7 +2819,8 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra) do_write_image_or_movie(re, scene, mh); } } else { - re->test_break(re->tbh); + if(re->test_break(re->tbh)) + G.afbreek= 1; } } } else { @@ -2769,9 +2866,10 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra) do_render_all_options(re); - if(re->test_break(re->tbh) == 0) { + if(re->test_break(re->tbh) == 0) do_write_image_or_movie(re, scene, mh); - } + else + G.afbreek= 1; if(G.afbreek==1) { /* remove touched file */ @@ -3006,6 +3104,7 @@ static void external_render_3d(Render *re, RenderEngineType *type) { RenderEngine engine; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) { RE_FreeRenderResult(re->result); @@ -3014,6 +3113,7 @@ static void external_render_3d(Render *re, RenderEngineType *type) else re->result= new_render_result(re, &re->disprect, 0, 0); // XXX re->r.scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)); } + BLI_rw_mutex_unlock(&re->resultmutex); if(re->result==NULL) return; @@ -3027,6 +3127,7 @@ static void external_render_3d(Render *re, RenderEngineType *type) free_render_result(&engine.fullresult, engine.fullresult.first); + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if(re->result->exrhandle) { RenderResult *rr; @@ -3042,5 +3143,6 @@ static void external_render_3d(Render *re, RenderEngineType *type) read_render_result(re, 0); } + BLI_rw_mutex_unlock(&re->resultmutex); } diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 5f8cf5504fa..b7832e74cd1 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -92,6 +92,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa { DerivedMesh* dm; ParticleKey state; + ParticleSimulationData sim = {re->scene, ob, psys, NULL}; ParticleData *pa=NULL; float cfra = bsystem_time(re->scene, ob, (float)re->scene->r.cfra, 0.0); int i, childexists; @@ -120,7 +121,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa Mat4Invert(ob->imat, ob->obmat); total_particles = psys->totpart+psys->totchild; - psys->lattice=psys_get_lattice(re->scene,ob,psys); + psys->lattice=psys_get_lattice(&sim); pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6); alloc_point_data(pd, total_particles, data_used); @@ -133,7 +134,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa for (i=0, pa=psys->particles; i < total_particles; i++, pa++) { state.time = cfra; - if(psys_get_particle_state(re->scene, ob, psys, i, &state, 0)) { + if(psys_get_particle_state(&sim, i, &state, 0)) { VECCOPY(partco, state.co); diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index d2599f6050c..cce99d64b39 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -1343,7 +1343,8 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int /* mix colors based on shadfac (rgb + amount of light factor) */ addAlphaLight(is->col, shr.diff, shr.alpha, d*shi.mat->filter); } else if (shi.mat->material_type == MA_TYPE_VOLUME) { - addAlphaLight(is->col, shr.combined, shr.alpha, 1.0f); + QUATCOPY(is->col, shr.combined); + is->col[3] = 1.f; } if(depth>0 && is->col[3]>0.0f) { @@ -1900,7 +1901,8 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * else max_samples = 1; } else { if (do_soft) max_samples = lar->ray_totsamp; - else max_samples = (R.osa > 4)?R.osa:5; + else if (shi->depth == 0) max_samples = (R.osa > 4)?R.osa:5; + else max_samples = 1; } ray_shadow_jittered_coords(shi, max_samples, jitco, &totjitco); diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 621831fb341..30832db5c7d 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -1024,7 +1024,7 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma, float *vec, f externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta); yn= tin*mtex->colfac; - zn= tin*mtex->varfac; + zn= tin*mtex->alphafac; if(mtex->mapto & MAP_COL) { zn= 1.0-yn; @@ -1156,7 +1156,7 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta); //yn= tin*mtex->colfac; - //zn= tin*mtex->varfac; + //zn= tin*mtex->alphafac; if(mtex->mapto & MAP_COL) { tex[0]=tr; tex[1]=tg; @@ -1175,11 +1175,11 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater har->b= in[2]; } if(mtex->mapto & MAP_ALPHA) - har->alfa = texture_value_blend(mtex->def_var,har->alfa,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_ALPHA); + har->alfa = texture_value_blend(mtex->def_var,har->alfa,tin,mtex->alphafac,mtex->blendtype); if(mtex->mapto & MAP_HAR) - har->hard = 1.0+126.0*texture_value_blend(mtex->def_var,((float)har->hard)/127.0,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_HAR); + har->hard = 1.0+126.0*texture_value_blend(mtex->def_var,((float)har->hard)/127.0,tin,mtex->hardfac,mtex->blendtype); if(mtex->mapto & MAP_RAYMIRR) - har->hasize = 100.0*texture_value_blend(mtex->def_var,har->hasize/100.0,tin,mtex->varfac,mtex->blendtype,mtex->maptoneg & MAP_RAYMIRR); + har->hasize = 100.0*texture_value_blend(mtex->def_var,har->hasize/100.0,tin,mtex->raymirrfac,mtex->blendtype); /* now what on earth is this good for?? */ //if(mtex->texco & 16) { // har->alfa= tin; diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c index bd022e768f8..a416c2d2764 100644 --- a/source/blender/render/intern/source/sss.c +++ b/source/blender/render/intern/source/sss.c @@ -862,6 +862,7 @@ static void sss_create_tree_mat(Render *re, Material *mat) setting them back, maybe we need to create our own Render? */ /* do SSS preprocessing render */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); rr= re->result; osa= re->osa; osaflag= re->r.mode & R_OSA; @@ -872,12 +873,20 @@ static void sss_create_tree_mat(Render *re, Material *mat) re->sss_points= &points; re->sss_mat= mat; re->i.partsdone= 0; - re->result= NULL; - RE_TileProcessor(re, 0, !(re->r.mode & R_PREVIEWBUTS)); - RE_FreeRenderResult(re->result); + if(!(re->r.scemode & R_PREVIEWBUTS)) + re->result= NULL; + BLI_rw_mutex_unlock(&re->resultmutex); + + RE_TileProcessor(re, 0, 1); + + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + if(!(re->r.scemode & R_PREVIEWBUTS)) { + RE_FreeRenderResult(re->result); + re->result= rr; + } + BLI_rw_mutex_unlock(&re->resultmutex); - re->result= rr; re->i.partsdone= partsdone; re->sss_mat= NULL; re->sss_points= NULL; diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 2d2c01e0bf1..7b0e5d8abbc 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -721,7 +721,7 @@ static int evalnodes(Tex *tex, float *texvec, float *dxt, float *dyt, TexResult short rv = TEX_INT; bNodeTree *nodes = tex->nodetree; - ntreeTexExecTree(nodes, texres, texvec, dxt, dyt, thread, tex, which_output, R.r.cfra); + ntreeTexExecTree(nodes, texres, texvec, dxt, dyt, thread, tex, which_output, R.r.cfra, (R.r.scemode & R_NODE_PREVIEW)); if(texres->nor) rv |= TEX_NOR; rv |= TEX_RGB; @@ -1468,9 +1468,12 @@ void texture_rgb_blend(float *in, float *tex, float *out, float fact, float facg } } -float texture_value_blend(float tex, float out, float fact, float facg, int blendtype, int flip) +float texture_value_blend(float tex, float out, float fact, float facg, int blendtype) { float in=0.0, facm, col, scf; + int flip= (facg < 0.0f); + + facg= fabsf(facg); fact*= facg; facm= 1.0-fact; @@ -1631,7 +1634,7 @@ void do_material_tex(ShadeInput *shi) float fact, facm, factt, facmm, stencilTin=1.0; float texvec[3], dxt[3], dyt[3], tempvec[3], norvec[3], warpvec[3]={0.0f, 0.0f, 0.0f}, Tnor=1.0; int tex_nr, rgbnor= 0, warpdone=0; - float nu[3], nv[3], nn[3] = {0,0,0}, dudnu = 1.f, dudnv = 0.f, dvdnu = 0.f, dvdnv = 1.f; // bump mapping + float nu[3] = {0,0,0}, nv[3] = {0,0,0}, nn[3] = {0,0,0}, dudnu = 1.f, dudnv = 0.f, dvdnu = 0.f, dvdnv = 1.f; // bump mapping int nunvdone= 0; if (R.r.scemode & R_NO_TEX) return; @@ -1813,7 +1816,7 @@ void do_material_tex(ShadeInput *shi) TexResult ttexr = {0, 0, 0, 0, 0, texres.talpha, NULL}; // temp TexResult float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv; const int fromrgb = ((tex->type == TEX_IMAGE) || ((tex->flag & TEX_COLORBAND)!=0)); - const float bf = 0.04f*Tnor*((mtex->maptoneg & MAP_NORM) ? -mtex->norfac : mtex->norfac); + const float bf = 0.04f*Tnor*mtex->norfac; // disable internal bump eval float* nvec = texres.nor; texres.nor = NULL; @@ -2020,10 +2023,9 @@ void do_material_tex(ShadeInput *shi) /* mapping */ if(mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) { - float tcol[3], colfac; + float tcol[3]; /* stencil maps on the texture control slider, not texture intensity value */ - colfac= mtex->colfac*stencilTin; tcol[0]=texres.tr; tcol[1]=texres.tg; tcol[2]=texres.tb; @@ -2043,15 +2045,19 @@ void do_material_tex(ShadeInput *shi) } if(mtex->mapto & MAP_COL) { + float colfac= mtex->colfac*stencilTin; texture_rgb_blend(&shi->r, tcol, &shi->r, texres.tin, colfac, mtex->blendtype); } if(mtex->mapto & MAP_COLSPEC) { - texture_rgb_blend(&shi->specr, tcol, &shi->specr, texres.tin, colfac, mtex->blendtype); + float colspecfac= mtex->colspecfac*stencilTin; + texture_rgb_blend(&shi->specr, tcol, &shi->specr, texres.tin, colspecfac, mtex->blendtype); } if(mtex->mapto & MAP_COLMIR) { + float mirrfac= mtex->mirrfac*stencilTin; + // exception for envmap only if(tex->type==TEX_ENVMAP && mtex->blendtype==MTEX_BLEND) { - fact= texres.tin*colfac; + fact= texres.tin*mirrfac; facm= 1.0- fact; shi->refcol[0]= fact + facm*shi->refcol[0]; shi->refcol[1]= fact*tcol[0] + facm*shi->refcol[1]; @@ -2059,14 +2065,13 @@ void do_material_tex(ShadeInput *shi) shi->refcol[3]= fact*tcol[2] + facm*shi->refcol[3]; } else { - texture_rgb_blend(&shi->mirr, tcol, &shi->mirr, texres.tin, colfac, mtex->blendtype); + texture_rgb_blend(&shi->mirr, tcol, &shi->mirr, texres.tin, mirrfac, mtex->blendtype); } } } if( (mtex->mapto & MAP_NORM) ) { if(texres.nor) { - if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac; - else tex->norfac= mtex->norfac; + tex->norfac= mtex->norfac; /* we need to code blending modes for normals too once.. now 1 exception hardcoded */ @@ -2074,7 +2079,7 @@ void do_material_tex(ShadeInput *shi) /* qdn: for normalmaps, to invert the normalmap vector, it is better to negate x & y instead of subtracting the vector as was done before */ tex->norfac = mtex->norfac; - if (mtex->maptoneg & MAP_NORM) { + if (tex->norfac < 0.0f) { texres.nor[0] = -texres.nor[0]; texres.nor[1] = -texres.nor[1]; } @@ -2159,8 +2164,7 @@ void do_material_tex(ShadeInput *shi) /* Now that most textures offer both Nor and Intensity, allow */ /* both to work, and let user select with slider. */ if(texres.nor) { - if(mtex->maptoneg & MAP_DISPLACE) tex->norfac= -mtex->norfac; - else tex->norfac= mtex->norfac; + tex->norfac= mtex->norfac; shi->displace[0]+= 0.2f*Tnor*tex->norfac*texres.nor[0]; shi->displace[1]+= 0.2f*Tnor*tex->norfac*texres.nor[1]; @@ -2172,12 +2176,7 @@ void do_material_tex(ShadeInput *shi) else texres.tin= (0.35f*texres.tr+0.45f*texres.tg+0.2f*texres.tb); } - if(mtex->maptoneg & MAP_DISPLACE) { - factt= (texres.tin-0.5f)*mtex->dispfac*stencilTin; facmm= 1.0f-factt; - } - else { - factt= (0.5f-texres.tin)*mtex->dispfac*stencilTin; facmm= 1.0f-factt; - } + factt= (0.5f-texres.tin)*mtex->dispfac*stencilTin; facmm= 1.0f-factt; if(mtex->blendtype==MTEX_BLEND) { shi->displace[0]= factt*shi->vn[0] + facmm*shi->displace[0]; @@ -2200,7 +2199,6 @@ void do_material_tex(ShadeInput *shi) if(mtex->mapto & MAP_VARS) { /* stencil maps on the texture control slider, not texture intensity value */ - float varfac= mtex->varfac*stencilTin; if(rgbnor & TEX_RGB) { if(texres.talpha) texres.tin= texres.ta; @@ -2208,66 +2206,59 @@ void do_material_tex(ShadeInput *shi) } if(mtex->mapto & MAP_REF) { - int flip= mtex->maptoneg & MAP_REF; + float difffac= mtex->difffac*stencilTin; - shi->refl= texture_value_blend(mtex->def_var, shi->refl, texres.tin, varfac, mtex->blendtype, flip); + shi->refl= texture_value_blend(mtex->def_var, shi->refl, texres.tin, difffac, mtex->blendtype); if(shi->refl<0.0) shi->refl= 0.0; } if(mtex->mapto & MAP_SPEC) { - int flip= mtex->maptoneg & MAP_SPEC; + float specfac= mtex->specfac*stencilTin; - shi->spec= texture_value_blend(mtex->def_var, shi->spec, texres.tin, varfac, mtex->blendtype, flip); + shi->spec= texture_value_blend(mtex->def_var, shi->spec, texres.tin, specfac, mtex->blendtype); if(shi->spec<0.0) shi->spec= 0.0; } if(mtex->mapto & MAP_EMIT) { - int flip= mtex->maptoneg & MAP_EMIT; + float emitfac= mtex->emitfac*stencilTin; - shi->emit= texture_value_blend(mtex->def_var, shi->emit, texres.tin, varfac, mtex->blendtype, flip); + shi->emit= texture_value_blend(mtex->def_var, shi->emit, texres.tin, emitfac, mtex->blendtype); if(shi->emit<0.0) shi->emit= 0.0; } if(mtex->mapto & MAP_ALPHA) { - int flip= mtex->maptoneg & MAP_ALPHA; + float alphafac= mtex->alphafac*stencilTin; - shi->alpha= texture_value_blend(mtex->def_var, shi->alpha, texres.tin, varfac, mtex->blendtype, flip); + shi->alpha= texture_value_blend(mtex->def_var, shi->alpha, texres.tin, alphafac, mtex->blendtype); if(shi->alpha<0.0) shi->alpha= 0.0; else if(shi->alpha>1.0) shi->alpha= 1.0; } if(mtex->mapto & MAP_HAR) { - int flip= mtex->maptoneg & MAP_HAR; float har; // have to map to 0-1 + float hardfac= mtex->hardfac*stencilTin; har= ((float)shi->har)/128.0; - har= 128.0*texture_value_blend(mtex->def_var, har, texres.tin, varfac, mtex->blendtype, flip); + har= 128.0*texture_value_blend(mtex->def_var, har, texres.tin, hardfac, mtex->blendtype); if(har<1.0) shi->har= 1; else if(har>511.0) shi->har= 511; else shi->har= (int)har; } if(mtex->mapto & MAP_RAYMIRR) { - int flip= mtex->maptoneg & MAP_RAYMIRR; + float raymirrfac= mtex->raymirrfac*stencilTin; - shi->ray_mirror= texture_value_blend(mtex->def_var, shi->ray_mirror, texres.tin, varfac, mtex->blendtype, flip); + shi->ray_mirror= texture_value_blend(mtex->def_var, shi->ray_mirror, texres.tin, raymirrfac, mtex->blendtype); if(shi->ray_mirror<0.0) shi->ray_mirror= 0.0; else if(shi->ray_mirror>1.0) shi->ray_mirror= 1.0; } if(mtex->mapto & MAP_TRANSLU) { - int flip= mtex->maptoneg & MAP_TRANSLU; + float translfac= mtex->translfac*stencilTin; - shi->translucency= texture_value_blend(mtex->def_var, shi->translucency, texres.tin, varfac, mtex->blendtype, flip); + shi->translucency= texture_value_blend(mtex->def_var, shi->translucency, texres.tin, translfac, mtex->blendtype); if(shi->translucency<0.0) shi->translucency= 0.0; else if(shi->translucency>1.0) shi->translucency= 1.0; } - if(mtex->mapto & MAP_LAYER) { - int flip= mtex->maptoneg & MAP_LAYER; - - shi->layerfac= texture_value_blend(mtex->def_var, shi->layerfac, texres.tin, varfac, mtex->blendtype, flip); - if(shi->layerfac<0.0) shi->layerfac= 0.0; - else if(shi->layerfac>1.0) shi->layerfac= 1.0; - } if(mtex->mapto & MAP_AMB) { - int flip= mtex->maptoneg & MAP_AMB; + float ambfac= mtex->ambfac*stencilTin; - shi->amb= texture_value_blend(mtex->def_var, shi->amb, texres.tin, varfac, mtex->blendtype, flip); + shi->amb= texture_value_blend(mtex->def_var, shi->amb, texres.tin, ambfac, mtex->blendtype); if(shi->amb<0.0) shi->amb= 0.0; else if(shi->amb>1.0) shi->amb= 1.0; @@ -2385,11 +2376,10 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa } - if((mapto_flag & (MAP_EMISSION_COL+MAP_ABSORPTION_COL)) && (mtex->mapto & (MAP_EMISSION_COL+MAP_ABSORPTION_COL))) { - float tcol[3], colfac; + if((mapto_flag & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL)) && (mtex->mapto & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL))) { + float tcol[3]; /* stencil maps on the texture control slider, not texture intensity value */ - colfac= mtex->colfac*stencilTin; if((rgbnor & TEX_RGB)==0) { tcol[0]= mtex->r; @@ -2410,18 +2400,23 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa /* used for emit */ if((mapto_flag & MAP_EMISSION_COL) && (mtex->mapto & MAP_EMISSION_COL)) { - texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype); + float colemitfac= mtex->colemitfac*stencilTin; + texture_rgb_blend(col, tcol, col, texres.tin, colemitfac, mtex->blendtype); + } + + if((mapto_flag & MAP_REFLECTION_COL) && (mtex->mapto & MAP_REFLECTION_COL)) { + float colreflfac= mtex->colreflfac*stencilTin; + texture_rgb_blend(col, tcol, col, texres.tin, colreflfac, mtex->blendtype); } - /* MAP_COLMIR is abused for absorption colour at the moment */ - if((mapto_flag & MAP_ABSORPTION_COL) && (mtex->mapto & MAP_ABSORPTION_COL)) { - texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype); + if((mapto_flag & MAP_TRANSMISSION_COL) && (mtex->mapto & MAP_TRANSMISSION_COL)) { + float coltransfac= mtex->coltransfac*stencilTin; + texture_rgb_blend(col, tcol, col, texres.tin, coltransfac, mtex->blendtype); } } if((mapto_flag & MAP_VARS) && (mtex->mapto & MAP_VARS)) { /* stencil maps on the texture control slider, not texture intensity value */ - float varfac= mtex->varfac*stencilTin; /* convert RGB to intensity if intensity info isn't provided */ if (!(rgbnor & TEX_INT)) { @@ -2432,27 +2427,27 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa } if((mapto_flag & MAP_EMISSION) && (mtex->mapto & MAP_EMISSION)) { - int flip= mtex->maptoneg & MAP_EMISSION; + float emitfac= mtex->emitfac*stencilTin; - *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip); + *val = texture_value_blend(mtex->def_var, *val, texres.tin, emitfac, mtex->blendtype); if(*val<0.0) *val= 0.0; } if((mapto_flag & MAP_DENSITY) && (mtex->mapto & MAP_DENSITY)) { - int flip= mtex->maptoneg & MAP_DENSITY; + float densfac= mtex->densfac*stencilTin; - *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip); + *val = texture_value_blend(mtex->def_var, *val, texres.tin, densfac, mtex->blendtype); CLAMP(*val, 0.0, 1.0); } - if((mapto_flag & MAP_ABSORPTION) && (mtex->mapto & MAP_ABSORPTION)) { - int flip= mtex->maptoneg & MAP_ABSORPTION; + if((mapto_flag & MAP_SCATTERING) && (mtex->mapto & MAP_SCATTERING)) { + float scatterfac= mtex->scatterfac*stencilTin; - *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip); + *val = texture_value_blend(mtex->def_var, *val, texres.tin, scatterfac, mtex->blendtype); CLAMP(*val, 0.0, 1.0); } - if((mapto_flag & MAP_SCATTERING) && (mtex->mapto & MAP_SCATTERING)) { - int flip= mtex->maptoneg & MAP_SCATTERING; + if((mapto_flag & MAP_REFLECTION) && (mtex->mapto & MAP_REFLECTION)) { + float reflfac= mtex->reflfac*stencilTin; - *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip); + *val = texture_value_blend(mtex->def_var, *val, texres.tin, reflfac, mtex->blendtype); CLAMP(*val, 0.0, 1.0); } } @@ -2767,7 +2762,7 @@ void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, f if(mtex->mapto & WOMAP_BLEND) { if(rgb) texres.tin= (0.35*texres.tr+0.45*texres.tg+0.2*texres.tb); - *blend= texture_value_blend(mtex->def_var, *blend, texres.tin, mtex->varfac, mtex->blendtype, 0); + *blend= texture_value_blend(mtex->def_var, *blend, texres.tin, mtex->blendfac, mtex->blendtype); } } } diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c index 15d8643fea4..7ecaf83ae27 100644 --- a/source/blender/render/intern/source/volume_precache.c +++ b/source/blender/render/intern/source/volume_precache.c @@ -185,9 +185,9 @@ static float get_avg_surrounds(float *cache, int *res, int xx, int yy, int zz) } } - tot /= added; + if (added > 0) tot /= added; - return ((added>0)?tot:0.0f); + return tot; } /* function to filter the edges of the light cache, where there was no volume originally. @@ -202,17 +202,54 @@ static void lightcache_filter(VolumePrecache *vp) for (y=0; y < vp->res[1]; y++) { for (x=0; x < vp->res[0]; x++) { /* trigger for outside mesh */ - if (vp->data_r[ V_I(x, y, z, vp->res) ] < -0.5f) + if (vp->data_r[ V_I(x, y, z, vp->res) ] < -0.f) vp->data_r[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_r, vp->res, x, y, z); - if (vp->data_g[ V_I(x, y, z, vp->res) ] < -0.5f) + if (vp->data_g[ V_I(x, y, z, vp->res) ] < -0.f) vp->data_g[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_g, vp->res, x, y, z); - if (vp->data_b[ V_I(x, y, z, vp->res) ] < -0.5f) + if (vp->data_b[ V_I(x, y, z, vp->res) ] < -0.f) vp->data_b[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_b, vp->res, x, y, z); } } } } +static void lightcache_filter2(VolumePrecache *vp) +{ + int x, y, z; + float *new_r, *new_g, *new_b; + int field_size = vp->res[0]*vp->res[1]*vp->res[2]*sizeof(float); + + new_r = MEM_mallocN(field_size, "temp buffer for light cache filter r channel"); + new_g = MEM_mallocN(field_size, "temp buffer for light cache filter g channel"); + new_b = MEM_mallocN(field_size, "temp buffer for light cache filter b channel"); + + memcpy(new_r, vp->data_r, field_size); + memcpy(new_g, vp->data_g, field_size); + memcpy(new_b, vp->data_b, field_size); + + for (z=0; z < vp->res[2]; z++) { + for (y=0; y < vp->res[1]; y++) { + for (x=0; x < vp->res[0]; x++) { + /* trigger for outside mesh */ + if (vp->data_r[ V_I(x, y, z, vp->res) ] < -0.f) + new_r[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_r, vp->res, x, y, z); + if (vp->data_g[ V_I(x, y, z, vp->res) ] < -0.f) + new_g[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_g, vp->res, x, y, z); + if (vp->data_b[ V_I(x, y, z, vp->res) ] < -0.f) + new_b[ V_I(x, y, z, vp->res) ] = get_avg_surrounds(vp->data_b, vp->res, x, y, z); + } + } + } + + SWAP(float *, vp->data_r, new_r); + SWAP(float *, vp->data_g, new_g); + SWAP(float *, vp->data_b, new_b); + + if (new_r) { MEM_freeN(new_r); new_r=NULL; } + if (new_g) { MEM_freeN(new_g); new_g=NULL; } + if (new_b) { MEM_freeN(new_b); new_b=NULL; } +} + static inline int ms_I(int x, int y, int z, int *n) //has a pad of 1 voxel surrounding the core for boundary simulation { return z*(n[1]+2)*(n[0]+2) + y*(n[0]+2) + x; @@ -423,11 +460,10 @@ static void *vol_precache_part(void *data) ObjectInstanceRen *obi = pa->obi; RayTree *tree = pa->tree; ShadeInput *shi = pa->shi; - float density, scatter_col[3] = {0.f, 0.f, 0.f}; + float scatter_col[3] = {0.f, 0.f, 0.f}; float co[3]; int x, y, z; const int res[3]= {pa->res[0], pa->res[1], pa->res[2]}; - const float stepsize = vol_get_stepsize(shi, STEPSIZE_VIEW); for (z= pa->minz; z < pa->maxz; z++) { co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 0.5f)); @@ -448,8 +484,7 @@ static void *vol_precache_part(void *data) VecCopyf(shi->view, co); Normalize(shi->view); - density = vol_get_density(shi, co); - vol_get_scattering(shi, scatter_col, co, stepsize, density); + vol_get_scattering(shi, scatter_col, co); obi->volume_precache->data_r[ V_I(x, y, z, res) ] = scatter_col[0]; obi->volume_precache->data_g[ V_I(x, y, z, res) ] = scatter_col[1]; diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index bc425c8a1a3..381a32de027 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -170,29 +170,6 @@ static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, float *co, float *co } } -/* input shader data */ - -float vol_get_stepsize(struct ShadeInput *shi, int context) -{ - if (shi->mat->vol.stepsize_type == MA_VOL_STEP_RANDOMIZED) { - /* range between 0.75 and 1.25 */ - const float rnd = 0.5f * BLI_thread_frand(shi->thread) + 0.75f; - - if (context == STEPSIZE_VIEW) - return shi->mat->vol.stepsize * rnd; - else if (context == STEPSIZE_SHADE) - return shi->mat->vol.shade_stepsize * rnd; - } - else { // MA_VOL_STEP_CONSTANT - - if (context == STEPSIZE_VIEW) - return shi->mat->vol.stepsize; - else if (context == STEPSIZE_SHADE) - return shi->mat->vol.shade_stepsize; - } - - return shi->mat->vol.stepsize; -} /* trilinear interpolation */ static void vol_get_precached_scattering(ShadeInput *shi, float *scatter_col, float *co) @@ -212,9 +189,9 @@ static void vol_get_precached_scattering(ShadeInput *shi, float *scatter_col, fl sample_co[1] = ((co[1] - bbmin[1]) / dim[1]); sample_co[2] = ((co[2] - bbmin[2]) / dim[2]); - scatter_col[0] = voxel_sample_trilinear(vp->data_r, vp->res, sample_co); - scatter_col[1] = voxel_sample_trilinear(vp->data_g, vp->res, sample_co); - scatter_col[2] = voxel_sample_trilinear(vp->data_b, vp->res, sample_co); + scatter_col[0] = voxel_sample_triquadratic(vp->data_r, vp->res, sample_co); + scatter_col[1] = voxel_sample_triquadratic(vp->data_g, vp->res, sample_co); + scatter_col[2] = voxel_sample_triquadratic(vp->data_b, vp->res, sample_co); } /* Meta object density, brute force for now @@ -270,7 +247,8 @@ float vol_get_density(struct ShadeInput *shi, float *co) float density = shi->mat->vol.density; float density_scale = shi->mat->vol.density_scale; - do_volume_tex(shi, co, MAP_DENSITY, NULL, &density); + if (shi->mat->mapto_textured & MAP_DENSITY) + do_volume_tex(shi, co, MAP_DENSITY, NULL, &density); // if meta-object, modulate by metadensity without increasing it if (shi->obi->obr->ob->type == OB_MBALL) { @@ -281,79 +259,110 @@ float vol_get_density(struct ShadeInput *shi, float *co) return density * density_scale; } -/* scattering multiplier, values above 1.0 are non-physical, - * but can be useful to tweak lighting */ -float vol_get_scattering_fac(ShadeInput *shi, float *co) + +/* Color of light that gets scattered out by the volume */ +/* Uses same physically based scattering parameter as in transmission calculations, + * along with artificial reflection scale/reflection color tint */ +void vol_get_reflection_color(ShadeInput *shi, float *ref_col, float *co) { float scatter = shi->mat->vol.scattering; - float col[3] = {0.0, 0.0, 0.0}; + float reflection= shi->mat->vol.reflection; + VECCOPY(ref_col, shi->mat->vol.reflection_col); + + if (shi->mat->mapto_textured & (MAP_SCATTERING+MAP_REFLECTION_COL)) + do_volume_tex(shi, co, MAP_SCATTERING+MAP_REFLECTION_COL, ref_col, &scatter); - do_volume_tex(shi, co, MAP_SCATTERING, col, &scatter); + /* only one single float parameter at a time... :s */ + if (shi->mat->mapto_textured & (MAP_REFLECTION)) + do_volume_tex(shi, co, MAP_REFLECTION, NULL, &reflection); - return scatter; + ref_col[0] = reflection * ref_col[0] * scatter; + ref_col[1] = reflection * ref_col[1] * scatter; + ref_col[2] = reflection * ref_col[2] * scatter; } /* compute emission component, amount of radiance to add per segment * can be textured with 'emit' */ -void vol_get_emission(ShadeInput *shi, float *emission_col, float *co, float density) +void vol_get_emission(ShadeInput *shi, float *emission_col, float *co) { float emission = shi->mat->vol.emission; VECCOPY(emission_col, shi->mat->vol.emission_col); - do_volume_tex(shi, co, MAP_EMISSION+MAP_EMISSION_COL, emission_col, &emission); + if (shi->mat->mapto_textured & (MAP_EMISSION+MAP_EMISSION_COL)) + do_volume_tex(shi, co, MAP_EMISSION+MAP_EMISSION_COL, emission_col, &emission); - emission_col[0] = emission_col[0] * emission * density; - emission_col[1] = emission_col[1] * emission * density; - emission_col[2] = emission_col[2] * emission * density; + emission_col[0] = emission_col[0] * emission; + emission_col[1] = emission_col[1] * emission; + emission_col[2] = emission_col[2] * emission; } -void vol_get_absorption(ShadeInput *shi, float *absorb_col, float *co) + +/* A combination of scattering and absorption -> known as sigma T. + * This can possibly use a specific scattering colour, + * and absorption multiplier factor too, but these parameters are left out for simplicity. + * It's easy enough to get a good wide range of results with just these two parameters. */ +void vol_get_sigma_t(ShadeInput *shi, float *sigma_t, float *co) { - float absorption = shi->mat->vol.absorption; - VECCOPY(absorb_col, shi->mat->vol.absorption_col); + /* technically absorption, but named transmission color + * since it describes the effect of the coloring *after* absorption */ + float transmission_col[3] = {shi->mat->vol.transmission_col[0], shi->mat->vol.transmission_col[1], shi->mat->vol.transmission_col[2]}; + float scattering = shi->mat->vol.scattering; - do_volume_tex(shi, co, MAP_ABSORPTION+MAP_ABSORPTION_COL, absorb_col, &absorption); + if (shi->mat->mapto_textured & (MAP_SCATTERING+MAP_TRANSMISSION_COL)) + do_volume_tex(shi, co, MAP_SCATTERING+MAP_TRANSMISSION_COL, transmission_col, &scattering); - absorb_col[0] = (1.0f - absorb_col[0]) * absorption; - absorb_col[1] = (1.0f - absorb_col[1]) * absorption; - absorb_col[2] = (1.0f - absorb_col[2]) * absorption; + sigma_t[0] = (1.0f - transmission_col[0]) + scattering; + sigma_t[1] = (1.0f - transmission_col[1]) + scattering; + sigma_t[2] = (1.0f - transmission_col[2]) + scattering; } /* phase function - determines in which directions the light * is scattered in the volume relative to incoming direction * and view direction */ -float vol_get_phasefunc(ShadeInput *shi, short phasefunc_type, float g, float *w, float *wp) +float vol_get_phasefunc(ShadeInput *shi, float g, float *w, float *wp) { - const float costheta = Inpf(w, wp); - const float scale = M_PI; - - /* - * Scale constant is required, since Blender's shading system doesn't normalise for - * energy conservation - eg. scaling by 1/pi for a lambert shader. - * This makes volumes darker than other solid objects, for the same lighting intensity. - * To correct this, scale up the phase function values + const float normalize = 0.25f; // = 1.f/4.f = M_PI/(4.f*M_PI) + + /* normalization constant is 1/4 rather than 1/4pi, since + * Blender's shading system doesn't normalise for + * energy conservation - eg. multiplying by pdf ( 1/pi for a lambert brdf ). + * This means that lambert surfaces in Blender are pi times brighter than they 'should be' + * and therefore, with correct energy conservation, volumes will darker than other solid objects, + * for the same lighting intensity. + * To correct this, scale up the phase function values by pi * until Blender's shading system supports this better. --matt */ + if (g == 0.f) { /* isotropic */ + return normalize * 1.f; + } else { /* schlick */ + const float k = 1.55f * g - .55f * g * g * g; + const float kcostheta = k * Inpf(w, wp); + return normalize * (1.f - k*k) / ((1.f - kcostheta) * (1.f - kcostheta)); + } + + /* + * not used, but here for reference: switch (phasefunc_type) { case MA_VOL_PH_MIEHAZY: - return scale * (0.5f + 4.5f * powf(0.5 * (1.f + costheta), 8.f)) / (4.f*M_PI); + return normalize * (0.5f + 4.5f * powf(0.5 * (1.f + costheta), 8.f)); case MA_VOL_PH_MIEMURKY: - return scale * (0.5f + 16.5f * powf(0.5 * (1.f + costheta), 32.f)) / (4.f*M_PI); + return normalize * (0.5f + 16.5f * powf(0.5 * (1.f + costheta), 32.f)); case MA_VOL_PH_RAYLEIGH: - return scale * 3.f/(16.f*M_PI) * (1 + costheta * costheta); + return normalize * 3.f/4.f * (1 + costheta * costheta); case MA_VOL_PH_HG: - return scale * (1.f / (4.f * M_PI) * (1.f - g*g) / powf(1.f + g*g - 2.f * g * costheta, 1.5f)); + return normalize * (1.f - g*g) / powf(1.f + g*g - 2.f * g * costheta, 1.5f)); case MA_VOL_PH_SCHLICK: { const float k = 1.55f * g - .55f * g * g * g; const float kcostheta = k * costheta; - return scale * (1.f / (4.f * M_PI) * (1.f - k*k) / ((1.f - kcostheta) * (1.f - kcostheta))); + return normalize * (1.f - k*k) / ((1.f - kcostheta) * (1.f - kcostheta)); } case MA_VOL_PH_ISOTROPIC: default: - return scale * (1.f / (4.f * M_PI)); + return normalize * 1.f; } + */ } /* Compute transmittance = e^(-attenuation) */ @@ -361,15 +370,15 @@ void vol_get_transmittance_seg(ShadeInput *shi, float *tr, float stepsize, float { /* input density = density at co */ float tau[3] = {0.f, 0.f, 0.f}; - float absorb[3]; - const float scatter_dens = vol_get_scattering_fac(shi, co) * density * stepsize; - - vol_get_absorption(shi, absorb, co); + const float stepd = density * stepsize; + float sigma_t[3]; + + vol_get_sigma_t(shi, sigma_t, co); /* homogenous volume within the sampled distance */ - tau[0] += scatter_dens * absorb[0]; - tau[1] += scatter_dens * absorb[1]; - tau[2] += scatter_dens * absorb[2]; + tau[0] += stepd * sigma_t[0]; + tau[1] += stepd * sigma_t[1]; + tau[2] += stepd * sigma_t[2]; tr[0] *= exp(-tau[0]); tr[1] *= exp(-tau[1]); @@ -381,31 +390,29 @@ static void vol_get_transmittance(ShadeInput *shi, float *tr, float *co, float * { float p[3] = {co[0], co[1], co[2]}; float step_vec[3] = {endco[0] - co[0], endco[1] - co[1], endco[2] - co[2]}; - //const float ambtau = -logf(shi->mat->vol.depth_cutoff); // never zero float tau[3] = {0.f, 0.f, 0.f}; float t0 = 0.f; float t1 = Normalize(step_vec); float pt0 = t0; - t0 += shi->mat->vol.shade_stepsize * ((shi->mat->vol.stepsize_type == MA_VOL_STEP_CONSTANT) ? 0.5f : BLI_thread_frand(shi->thread)); + t0 += shi->mat->vol.stepsize * ((shi->mat->vol.stepsize_type == MA_VOL_STEP_CONSTANT) ? 0.5f : BLI_thread_frand(shi->thread)); p[0] += t0 * step_vec[0]; p[1] += t0 * step_vec[1]; p[2] += t0 * step_vec[2]; - VecMulf(step_vec, shi->mat->vol.shade_stepsize); + VecMulf(step_vec, shi->mat->vol.stepsize); - for (; t0 < t1; pt0 = t0, t0 += shi->mat->vol.shade_stepsize) { - float absorb[3]; + for (; t0 < t1; pt0 = t0, t0 += shi->mat->vol.stepsize) { const float d = vol_get_density(shi, p); const float stepd = (t0 - pt0) * d; - const float scatter_dens = vol_get_scattering_fac(shi, p) * stepd; - vol_get_absorption(shi, absorb, p); + float sigma_t[3]; + + vol_get_sigma_t(shi, sigma_t, co); - tau[0] += scatter_dens * absorb[0]; - tau[1] += scatter_dens * absorb[1]; - tau[2] += scatter_dens * absorb[2]; + tau[0] += stepd * sigma_t[0]; + tau[1] += stepd * sigma_t[1]; + tau[2] += stepd * sigma_t[2]; - //if (luminance(tau) >= ambtau) break; VecAddf(p, p, step_vec); } @@ -420,9 +427,7 @@ void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float * float visifac, lv[3], lampdist; float tr[3]={1.0,1.0,1.0}; float hitco[3], *atten_co; - float p; - float scatter_fac; - float shade_stepsize = vol_get_stepsize(shi, STEPSIZE_SHADE); + float p, ref_col[3]; if (lar->mode & LA_LAYER) if((lar->lay & shi->obi->lay)==0) return; if ((lar->lay & shi->lay)==0) return; @@ -476,15 +481,20 @@ void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float * } } - p = vol_get_phasefunc(shi, shi->mat->vol.phasefunc_type, shi->mat->vol.phasefunc_g, shi->view, lv); - VecMulf(lacol, p); + if (luminance(lacol) < 0.001f) return; + + p = vol_get_phasefunc(shi, shi->mat->vol.asymmetry, shi->view, lv); + + /* physically based scattering with non-physically based RGB gain */ + vol_get_reflection_color(shi, ref_col, co); - scatter_fac = vol_get_scattering_fac(shi, co); - VecMulf(lacol, scatter_fac); + lacol[0] *= p * ref_col[0]; + lacol[1] *= p * ref_col[1]; + lacol[2] *= p * ref_col[2]; } /* single scattering only for now */ -void vol_get_scattering(ShadeInput *shi, float *scatter_col, float *co, float stepsize, float density) +void vol_get_scattering(ShadeInput *shi, float *scatter_col, float *co) { ListBase *lights; GroupObject *go; @@ -516,71 +526,69 @@ outgoing radiance from behind surface * beam transmittance/attenuation --> radiance for each segment = (radiance added by scattering + radiance added by emission) * beam transmittance/attenuation */ + +/* For ease of use, I've also introduced a 'reflection' and 'reflection color' parameter, which isn't + * physically correct. This works as an RGB tint/gain on out-scattered light, but doesn't affect the light + * that is transmitted through the volume. While having wavelength dependent absorption/scattering is more correct, + * it also makes it harder to control the overall look of the volume since colouring the outscattered light results + * in the inverse colour being transmitted through the rest of the volume. + */ static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float *endco) { - float tr[3] = {1.0f, 1.0f, 1.0f}; - float radiance[3] = {0.f, 0.f, 0.f}, d_radiance[3] = {0.f, 0.f, 0.f}; - float stepsize = vol_get_stepsize(shi, STEPSIZE_VIEW); - int nsteps, s; - float emit_col[3], scatter_col[3] = {0.0, 0.0, 0.0}; - float stepvec[3], step_sta[3], step_end[3], step_mid[3]; - float density; - const float depth_cutoff = shi->mat->vol.depth_cutoff; - - /* ray marching */ - nsteps = (int)((VecLenf(co, endco) / stepsize) + 0.5); - - VecSubf(stepvec, endco, co); - VecMulf(stepvec, 1.0f / nsteps); - VecCopyf(step_sta, co); - VecAddf(step_end, step_sta, stepvec); - - /* get radiance from all points along the ray due to participating media */ - for (s = 0; s < nsteps; s++) { - - density = vol_get_density(shi, step_sta); + float radiance[3] = {0.f, 0.f, 0.f}; + float tr[3] = {1.f, 1.f, 1.f}; + float p[3] = {co[0], co[1], co[2]}; + float step_vec[3] = {endco[0] - co[0], endco[1] - co[1], endco[2] - co[2]}; + const float stepsize = shi->mat->vol.stepsize; + + float t0 = 0.f; + float pt0 = t0; + float t1 = Normalize(step_vec); /* returns vector length */ + + t0 += stepsize * ((shi->mat->vol.stepsize_type == MA_VOL_STEP_CONSTANT) ? 0.5f : BLI_thread_frand(shi->thread)); + p[0] += t0 * step_vec[0]; + p[1] += t0 * step_vec[1]; + p[2] += t0 * step_vec[2]; + VecMulf(step_vec, stepsize); + + for (; t0 < t1; pt0 = t0, t0 += stepsize) { + const float density = vol_get_density(shi, p); - /* there's only any use in shading here if there's actually some density to shade! */ if (density > 0.01f) { - + float scatter_col[3], emit_col[3]; + const float stepd = (t0 - pt0) * density; + /* transmittance component (alpha) */ vol_get_transmittance_seg(shi, tr, stepsize, co, density); - - step_mid[0] = step_sta[0] + (stepvec[0] * 0.5); - step_mid[1] = step_sta[1] + (stepvec[1] * 0.5); - step_mid[2] = step_sta[2] + (stepvec[2] * 0.5); - - /* incoming light via emission or scattering (additive) */ - vol_get_emission(shi, emit_col, step_mid, density); - if (shi->obi->volume_precache) - vol_get_precached_scattering(shi, scatter_col, step_mid); - else - vol_get_scattering(shi, scatter_col, step_mid, stepsize, density); + if (luminance(tr) < shi->mat->vol.depth_cutoff) break; - VecMulf(scatter_col, density); - VecAddf(d_radiance, emit_col, scatter_col); + vol_get_emission(shi, emit_col, p); - /* Lv += Tr * (Lve() + Ld) */ - VecMulVecf(d_radiance, tr, d_radiance); - VecMulf(d_radiance, stepsize); + if (shi->obi->volume_precache) { + float p2[3]; + + p2[0] = p[0] + (step_vec[0] * 0.5); + p2[1] = p[1] + (step_vec[1] * 0.5); + p2[2] = p[2] + (step_vec[2] * 0.5); + + vol_get_precached_scattering(shi, scatter_col, p2); + } else + vol_get_scattering(shi, scatter_col, p); - VecAddf(radiance, radiance, d_radiance); + radiance[0] += stepd * tr[0] * (emit_col[0] + scatter_col[0]); + radiance[1] += stepd * tr[1] * (emit_col[1] + scatter_col[1]); + radiance[2] += stepd * tr[2] * (emit_col[2] + scatter_col[2]); } - - VecCopyf(step_sta, step_end); - VecAddf(step_end, step_end, stepvec); - - /* luminance rec. 709 */ - if ((0.2126*tr[0] + 0.7152*tr[1] + 0.0722*tr[2]) < depth_cutoff) break; + VecAddf(p, p, step_vec); } - /* multiply original color (behind volume) with beam transmittance over entire distance */ - VecMulVecf(col, tr, col); + /* multiply original color (from behind volume) with transmittance over entire distance */ + VecMulVecf(col, tr, col); VecAddf(col, col, radiance); /* alpha <-- transmission luminance */ - col[3] = 1.0f -(0.2126*tr[0] + 0.7152*tr[1] + 0.0722*tr[2]); + col[3] = 1.0f - luminance(tr); } /* the main entry point for volume shading */ @@ -607,7 +615,7 @@ static void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr, int in /* don't render the backfaces of ztransp volume materials. * volume shading renders the internal volume from between the - * near view intersection of the solid volume to the + * ' view intersection of the solid volume to the * intersection on the other side, as part of the shading of * the front face. @@ -683,7 +691,6 @@ void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct float hitco[3]; float tr[3] = {1.0,1.0,1.0}; Isect is; - float shade_stepsize = vol_get_stepsize(shi, STEPSIZE_SHADE); float *startco, *endco; float density=0.f; @@ -711,8 +718,7 @@ void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct vol_get_transmittance(shi, tr, startco, endco); VecCopyf(shr->combined, tr); - shr->combined[3] = 1.0f -(0.2126*tr[0] + 0.7152*tr[1] + 0.0722*tr[2]); - shr->alpha = shr->combined[3]; + shr->combined[3] = 1.0f - luminance(tr); } @@ -749,4 +755,4 @@ void shade_volume_inside(ShadeInput *shi, ShadeResult *shr) shi->mat = mat_backup; shi->obi = obi_backup; shi->obr = obi_backup->obr; -}
\ No newline at end of file +} diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c index 17858e55e3d..479f33c9ff2 100644 --- a/source/blender/render/intern/source/voxeldata.c +++ b/source/blender/render/intern/source/voxeldata.c @@ -167,12 +167,10 @@ void init_frame_smoke(Render *re, VoxelData *vd, Tex *tex) SmokeModifierData *smd = (SmokeModifierData *)md; if(smd->domain && smd->domain->fluid) { - //int big = (smd->domain->flags & MOD_SMOKE_HIGHRES); - int big=0; - if (big) { - //smoke_turbulence_get_res(smd->domain->wt, vd->resol); - //vd->dataset = smoke_turbulence_get_density(smd->domain->wt); + if (smd->domain->flags & MOD_SMOKE_HIGHRES) { + smoke_turbulence_get_res(smd->domain->wt, vd->resol); + vd->dataset = smoke_turbulence_get_density(smd->domain->wt); } else { VECCOPY(vd->resol, smd->domain->res); vd->dataset = smoke_get_density(smd->domain->fluid); @@ -228,9 +226,6 @@ void make_voxeldata(struct Render *re) { Tex *tex; - if(re->scene->r.scemode & R_PREVIEWBUTS) - return; - re->i.infostr= "Loading voxel datasets"; re->stats_draw(re->sdh, &re->i); @@ -261,9 +256,6 @@ void free_voxeldata(Render *re) { Tex *tex; - if(re->scene->r.scemode & R_PREVIEWBUTS) - return; - for (tex= G.main->tex.first; tex; tex= tex->id.next) { if(tex->id.us && tex->type==TEX_VOXELDATA) { free_voxeldata_one(re, tex); |