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:
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/CMakeLists.txt4
-rw-r--r--source/blender/render/SConscript8
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h7
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h2
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h1
-rw-r--r--source/blender/render/intern/include/render_types.h4
-rw-r--r--source/blender/render/intern/include/volume_precache.h2
-rw-r--r--source/blender/render/intern/include/volumetric.h3
-rw-r--r--source/blender/render/intern/source/convertblender.c61
-rw-r--r--source/blender/render/intern/source/pipeline.c172
-rw-r--r--source/blender/render/intern/source/pointdensity.c5
-rw-r--r--source/blender/render/intern/source/rayshade.c6
-rw-r--r--source/blender/render/intern/source/renderdatabase.c10
-rw-r--r--source/blender/render/intern/source/sss.c17
-rw-r--r--source/blender/render/intern/source/texture.c121
-rw-r--r--source/blender/render/intern/source/volume_precache.c53
-rw-r--r--source/blender/render/intern/source/volumetric.c286
-rw-r--r--source/blender/render/intern/source/voxeldata.c14
18 files changed, 481 insertions, 295 deletions
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index 3284f7ea79a..b30bc4936a5 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -34,6 +34,10 @@ SET(INC
../makesrna
)
+IF(WIN32)
+ SET(INC ${INC} ${PTHREADS_INC})
+ENDIF(WIN32)
+
IF(WITH_OPENEXR)
ADD_DEFINITIONS(-DWITH_OPENEXR)
ENDIF(WITH_OPENEXR)
diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript
index db151775b96..f6193c29eba 100644
--- a/source/blender/render/SConscript
+++ b/source/blender/render/SConscript
@@ -23,4 +23,12 @@ if env['WITH_BF_OPENEXR']:
if env['OURPLATFORM']=='linux2':
cflags='-pthread'
+
+if env['OURPLATFORM'] == 'linux2':
+ cflags='-pthread'
+ incs += ' ../../../extern/binreloc/include'
+
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
+ incs += ' ' + env['BF_PTHREADS_INC']
+
env.BlenderLib ( libname = 'bf_render', sources = sources, includes = Split(incs), defines=defs, libtype='core', priority=145, compileflags=cflags )
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index bf02af6ac36..56a81ac6b43 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -157,8 +157,11 @@ void RE_FreeAllRender (void);
/* get results and statistics */
void RE_FreeRenderResult(struct RenderResult *rr);
-struct RenderResult *RE_GetResult(struct Render *re);
-void RE_GetResultImage(struct Render *re, struct RenderResult *rr);
+struct RenderResult *RE_AcquireResultRead(struct Render *re);
+struct RenderResult *RE_AcquireResultWrite(struct Render *re);
+void RE_ReleaseResult(struct Render *re);
+void RE_AcquireResultImage(struct Render *re, struct RenderResult *rr);
+void RE_ReleaseResultImage(struct Render *re);
struct RenderStats *RE_GetStats(struct Render *re);
void RE_ResultGet32(struct Render *re, unsigned int *rect);
struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name);
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index 15b59f2c8cc..069861df992 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -55,7 +55,7 @@ int externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, f
/* particle.c */
void texture_rgb_blend(float *in, float *tex, float *out, float fact, float facg, int blendtype);
-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);
/* node_composite.c */
void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, float *result);
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 435e3ddc07f..134be189e8f 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -128,7 +128,6 @@ typedef struct ShadeInput
/* individual copies: */
int har; /* hardness */
- float layerfac;
/* texture coordinates */
float lo[3], gl[3], ref[3], orn[3], winco[3], sticky[3], vcol[4];
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);