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:
-rw-r--r--source/blender/blenkernel/intern/material.c1
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h1
-rw-r--r--source/blender/render/intern/source/shadeinput.c1
-rw-r--r--source/blender/render/intern/source/volumetric.c299
-rw-r--r--source/blender/src/buttons_shading.c47
6 files changed, 274 insertions, 77 deletions
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 3fcc76bf058..b47e4d2ebaa 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -173,6 +173,7 @@ void init_material(Material *ma)
ma->vol_absorption = 1.0f;
ma->vol_scattering = 1.0f;
ma->vol_absorption_col[0] = ma->vol_absorption_col[1] = ma->vol_absorption_col[2] = 0.0f;
+ ma->vol_precache_resolution = 50;
ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RADIO|MA_RAYBIAS|MA_TANGENT_STR;
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index a3e6a21dd0b..4af54832221 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -7895,6 +7895,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (ma->vol_density_scale < 0.0001f)
ma->vol_density_scale = 1.0f;
+ if (ma->vol_precache_resolution == 0)
+ ma->vol_precache_resolution = 50;
}
for(tex=main->tex.first; tex; tex= tex->id.next) {
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 112a1e9929d..5a320da522f 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -100,6 +100,7 @@ typedef struct ShadeInput
struct StrandRen *strand;
struct ObjectInstanceRen *obi;
struct ObjectRen *obr;
+ struct Render *re; /* link back to the Render */
int facenr;
float facenor[3]; /* copy from face */
short flippednor; /* is facenor flipped? */
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index aa11e3d75dd..6989fe66b67 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -1270,6 +1270,7 @@ void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, in
shi->combinedflag= ~rl->pass_xor;
shi->mat_override= rl->mat_override;
shi->light_override= rl->light_override;
+ shi->re = &R;
// shi->rl= rl;
/* note shi.depth==0 means first hit, not raytracing */
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
index fc2e4a630b1..0f6e7591ece 100644
--- a/source/blender/render/intern/source/volumetric.c
+++ b/source/blender/render/intern/source/volumetric.c
@@ -51,6 +51,7 @@
#include "BKE_main.h"
#include "render_types.h"
+#include "renderdatabase.h"
#include "pixelshading.h"
#include "shading.h"
#include "texture.h"
@@ -61,8 +62,6 @@
extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-#define PRECACHE_RES 5
-
static int vol_backface_intersect_check(Isect *is, int ob, RayFace *face)
{
VlakRen *vlr = (VlakRen *)face;
@@ -96,7 +95,7 @@ static int vol_always_intersect_check(Isect *is, int ob, RayFace *face)
/* TODO: Box or sphere intersection types could speed things up */
static int vol_get_bounds(ShadeInput *shi, float *co, float *vec, float *hitco, Isect *isect, int intersect_type, int checkfunc)
{
- float maxsize = RE_ray_tree_max_size(R.raytree);
+ float maxsize = RE_ray_tree_max_size(shi->re->raytree);
int intersected=0;
/* TODO: use object's bounding box to calculate max size */
@@ -115,9 +114,9 @@ static int vol_get_bounds(ShadeInput *shi, float *co, float *vec, float *hitco,
else if (intersect_type == VOL_BOUNDS_SS) isect->faceorig= NULL;
if (checkfunc==VOL_IS_BACKFACE)
- intersected = RE_ray_tree_intersect_check(R.raytree, isect, vol_backface_intersect_check);
+ intersected = RE_ray_tree_intersect_check(shi->re->raytree, isect, vol_backface_intersect_check);
else
- intersected = RE_ray_tree_intersect(R.raytree, isect);
+ intersected = RE_ray_tree_intersect(shi->re->raytree, isect);
if(intersected)
{
@@ -240,6 +239,82 @@ void vol_get_absorption(ShadeInput *shi, float *absorb_col, float *co)
absorb_col[2] = (1.0f - absorb_col[2]) * absorption;
}
+
+static float D(ShadeInput *shi, int rgb, int x, int y, int z)
+{
+ const int res = shi->mat->vol_precache_resolution;
+ CLAMP(x, 0, res-1);
+ CLAMP(y, 0, res-1);
+ CLAMP(y, 0, res-1);
+ return shi->obi->volume_precache[rgb*res*res*res + x*res*res + y*res + z];
+}
+
+inline float lerp(float t, float v1, float v2) {
+ return (1.f - t) * v1 + t * v2;
+}
+
+/* trilinear interpolation */
+static void vol_get_precached_scattering(ShadeInput *shi, float *scatter_col, float *co)
+{
+ const int res = shi->mat->vol_precache_resolution;
+ float voxx, voxy, voxz;
+ int vx, vy, vz;
+ float dx, dy, dz;
+ float d00, d10, d01, d11, d0, d1, d_final;
+ float bbmin[3], bbmax[3], dim[3];
+ int rgb;
+
+ if (!shi->obi->volume_precache) return;
+
+ VECCOPY(bbmin, shi->obi->obr->boundbox[0]);
+ VECCOPY(bbmax, shi->obi->obr->boundbox[1]);
+ VecSubf(dim, bbmax, bbmin);
+
+ voxx = ((co[0] - bbmin[0]) / dim[0]) * res - 0.5f;
+ voxy = ((co[1] - bbmin[1]) / dim[1]) * res - 0.5f;
+ voxz = ((co[2] - bbmin[2]) / dim[2]) * res - 0.5f;
+
+ vx = (int)voxx; vy = (int)voxy; vz = (int)voxz;
+
+ dx = voxx - vx; dy = voxy - vy; dz = voxz - vz;
+
+ for (rgb=0; rgb < 3; rgb++) {
+ d00 = lerp(dx, D(shi, rgb, vx, vy, vz), D(shi, rgb, vx+1, vy, vz));
+ d10 = lerp(dx, D(shi, rgb, vx, vy+1, vz), D(shi, rgb, vx+1, vy+1, vz));
+ d01 = lerp(dx, D(shi, rgb, vx, vy, vz+1), D(shi, rgb, vx+1, vy, vz+1));
+ d11 = lerp(dx, D(shi, rgb, vx, vy+1, vz+1), D(shi, rgb, vx+1, vy+1, vz+1));
+ d0 = lerp(dy, d00, d10);
+ d1 = lerp(dy, d01, d11);
+ d_final = lerp(dz, d0, d1);
+
+ scatter_col[rgb] = d_final;
+ }
+}
+
+#if 0
+/* no interpolation, not used */
+static void vol_get_precached_scattering_nearest(ShadeInput *shi, float *scatter_col, float *co)
+{
+ const int res = shi->mat->vol_precache_resolution;
+ int x,y,z;
+ float bbmin[3], bbmax[3], dim[3];
+
+ if (!shi->obi->volume_precache) return;
+
+ VECCOPY(bbmin, shi->obi->obr->boundbox[0]);
+ VECCOPY(bbmax, shi->obi->obr->boundbox[1]);
+ VecSubf(dim, bbmax, bbmin);
+
+ x = (int)(((co[0] - bbmin[0]) / dim[0]) * res);
+ y = (int)(((co[1] - bbmin[1]) / dim[1]) * res);
+ z = (int)(((co[2] - bbmin[2]) / dim[2]) * res);
+
+ scatter_col[0] = shi->obi->volume_precache[0*res*res*res + x*res*res + y*res + z];
+ scatter_col[1] = shi->obi->volume_precache[1*res*res*res + x*res*res + y*res + z];
+ scatter_col[2] = shi->obi->volume_precache[2*res*res*res + x*res*res + y*res + z];
+}
+#endif
+
/* Compute attenuation, otherwise known as 'optical thickness', extinction, or tau.
* Used in the relationship Transmittance = e^(-attenuation)
*/
@@ -276,7 +351,6 @@ void vol_get_attenuation(ShadeInput *shi, float *tau, float *co, float *endco, f
VecAddf(step_end, step_sta, step_vec);
for (s = 0; s < nsteps; s++) {
-
if (s > 0)
density = vol_get_density(shi, step_sta);
@@ -317,9 +391,9 @@ void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float *
shi->osatex= 0;
do_lamp_tex(lar, lv, shi, lacol, LA_TEXTURE);
}
-
+
VecMulf(lacol, visifac*lar->energy);
-
+
if (ELEM(lar->type, LA_SUN, LA_HEMI))
VECCOPY(lv, lar->vec);
VecMulf(lv, -1.0f);
@@ -364,27 +438,27 @@ void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float *
vol_get_scattering_fac(shi, &scatter_fac, co, density);
VecMulf(lacol, scatter_fac);
-
}
/* single scattering only for now */
-void vol_get_scattering(Render *re, ShadeInput *shi, float *scatter, float *co, float stepsize, float density)
+void vol_get_scattering(ShadeInput *shi, float *scatter, float *co, float stepsize, float density)
{
GroupObject *go;
ListBase *lights;
LampRen *lar;
float col[3] = {0.f, 0.f, 0.f};
-
- lights= get_lights(shi);
- for(go=lights->first; go; go= go->next)
+ int i=0;
+
+ for(go=shi->re->lights.first; go; go= go->next)
{
float lacol[3] = {0.f, 0.f, 0.f};
+ i++;
+
lar= go->lampren;
if (lar) {
-
vol_shade_one_lamp(shi, co, lar, lacol, stepsize, density);
-
+
VecMulf(lacol, density);
VecAddf(col, col, lacol);
@@ -415,7 +489,6 @@ static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float
VecMulVecf(radiance, tr, col);
tr[0] = tr[1] = tr[2] = 1.0f;
-
/* ray marching */
nsteps = (int)ceil(VecLenf(co, endco) / stepsize);
@@ -447,23 +520,12 @@ static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float
/* incoming light via emission or scattering (additive) */
vol_get_emission(shi, emit_col, step_mid, density);
- if ((shi->mat->vol_shadeflag & MA_VOL_PRECACHESHADING) && shi->obi->volume_precache) {
- const int res = shi->mat->vol_precache_resolution;
- int x,y,z;
- float bbmin[3], bbmax[3], dim[3];
-
- VECCOPY(bbmin, shi->obi->obr->boundbox[0]);
- VECCOPY(bbmax, shi->obi->obr->boundbox[1]);
- VecSubf(dim, bbmax, bbmin);
-
- x = (int)(((step_mid[0] - bbmin[0]) / dim[0]) * res);
- y = (int)(((step_mid[1] - bbmin[1]) / dim[1]) * res);
- z = (int)(((step_mid[2] - bbmin[2]) / dim[2]) * res);
-
- scatter_col[0] = scatter_col[1] = scatter_col[2] = shi->obi->volume_precache[x*res*res + y*res + z];
- }
- else
- vol_get_scattering(&R, shi, scatter_col, step_mid, stepsize, density);
+
+ if ((shi->mat->vol_shadeflag & MA_VOL_PRECACHESHADING) &&
+ (shi->mat->vol_shadeflag & MA_VOL_ATTENUATED)) {
+ vol_get_precached_scattering(shi, scatter_col, step_mid);
+ } else
+ vol_get_scattering(shi, scatter_col, step_mid, stepsize, density);
VecAddf(d_radiance, emit_col, scatter_col);
@@ -544,7 +606,7 @@ static void shade_intersection(ShadeInput *shi, float *col, Isect *is)
static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, float *co, float *col)
{
Isect isect;
- float maxsize = RE_ray_tree_max_size(R.raytree);
+ float maxsize = RE_ray_tree_max_size(shi->re->raytree);
VECCOPY(isect.start, co);
isect.end[0] = isect.start[0] + shi->view[0] * maxsize;
@@ -560,7 +622,7 @@ static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, float *co, float *co
isect.lay= -1;
/* check to see if there's anything behind the volume, otherwise shade the sky */
- if(RE_ray_tree_intersect(R.raytree, &isect)) {
+ if(RE_ray_tree_intersect(shi->re->raytree, &isect)) {
shade_intersection(shi, col, &isect);
} else {
shadeSkyView(col, co, shi->view, NULL);
@@ -568,6 +630,7 @@ static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, float *co, float *co
}
}
+/* the main entry point for volume shading */
void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr)
{
float hitco[3], col[4] = {0.f,0.f,0.f,0.f};
@@ -629,6 +692,8 @@ void volume_trace(struct ShadeInput *shi, struct ShadeResult *shr)
}
}
+/* Traces a shadow through the object,
+ * pretty much gets the transmission over a ray path */
void volume_trace_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is)
{
float hitco[3];
@@ -678,26 +743,125 @@ void volume_trace_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct
shr->combined[2] = 0.0f;
shr->combined[3] = shr->alpha = 0.0f;
}
+}
+
+
+/* Recursive test for intersections, from a point inside the mesh, to outside
+ * Number of intersections (depth) determine if a point is inside or outside the mesh */
+int intersect_outside_volume(RayTree *tree, Isect *isect, float *offset, int limit, int depth)
+{
+ if (limit == 0) return depth;
+
+ if (RE_ray_tree_intersect(tree, isect)) {
+ float hitco[3];
+
+ hitco[0] = isect->start[0] + isect->labda*isect->vec[0];
+ hitco[1] = isect->start[1] + isect->labda*isect->vec[1];
+ hitco[2] = isect->start[2] + isect->labda*isect->vec[2];
+ VecAddf(isect->start, hitco, offset);
+
+ return intersect_outside_volume(tree, isect, offset, limit-1, depth+1);
+ } else {
+ return depth;
+ }
+}
+/* Uses ray tracing to check if a point is inside or outside an ObjectInstanceRen */
+int point_inside_obi(RayTree *tree, ObjectInstanceRen *obi, float *co)
+{
+ float maxsize = RE_ray_tree_max_size(tree);
+ int intersected;
+ Isect isect;
+ float vec[3] = {0.0f,0.0f,1.0f};
+ int final_depth=0, depth=0, limit=20;
+
+ /* set up the isect */
+ memset(&isect, 0, sizeof(isect));
+ VECCOPY(isect.start, co);
+ isect.end[0] = co[0] + vec[0] * maxsize;
+ isect.end[1] = co[1] + vec[1] * maxsize;
+ isect.end[2] = co[2] + vec[2] * maxsize;
+
+ /* and give it a little offset to prevent self-intersections */
+ VecMulf(vec, 1e-5);
+ VecAddf(isect.start, isect.start, vec);
+
+ isect.mode= RE_RAY_MIRROR;
+ isect.face_last= NULL;
+ isect.lay= -1;
+
+ final_depth = intersect_outside_volume(tree, &isect, vec, limit, depth);
+
+ /* even number of intersections: point is outside
+ * odd number: point is inside */
+ if (final_depth % 2 == 0) return 0;
+ else return 1;
+}
+
+static int inside_check_func(Isect *is, int ob, RayFace *face)
+{
+ return 1;
+}
+static void vlr_face_coords(RayFace *face, float **v1, float **v2, float **v3, float **v4)
+{
+ VlakRen *vlr= (VlakRen*)face;
+
+ *v1 = (vlr->v1)? vlr->v1->co: NULL;
+ *v2 = (vlr->v2)? vlr->v2->co: NULL;
+ *v3 = (vlr->v3)? vlr->v3->co: NULL;
+ *v4 = (vlr->v4)? vlr->v4->co: NULL;
+}
+
+RayTree *create_raytree_obi(ObjectInstanceRen *obi, float *bbmin, float *bbmax)
+{
+ int v;
+ VlakRen *vlr= NULL;
+
+ /* create empty raytree */
+ RayTree *tree = RE_ray_tree_create(64, obi->obr->totvlak, bbmin, bbmax,
+ vlr_face_coords, inside_check_func, NULL, NULL);
+
+ /* fill it with faces */
+ for(v=0; v<obi->obr->totvlak; v++) {
+ if((v & 255)==0)
+ vlr= obi->obr->vlaknodes[v>>8].vlak;
+ else
+ vlr++;
+
+ RE_ray_tree_add_face(tree, 0, vlr);
+ }
+
+ RE_ray_tree_done(tree);
}
+/* Precache a volume into a 3D voxel grid.
+ * The voxel grid is stored in the ObjectInstanceRen,
+ * in camera space, aligned with the ObjectRen's bounding box.
+ * Resolution is defined by the user.
+ */
void vol_precache_objectinstance(Render *re, ObjectInstanceRen *obi, Material *ma, float *bbmin, float *bbmax)
{
int x, y, z;
float co[3], voxel[3], scatter_col[3];
ShadeInput shi;
+ float view[3] = {0.0,0.0,1.0};
float density;
float stepsize;
- float resf;
- int res_2;
- float res_3;
+ float resf, res_3f;
+ int res_2, res_3;
float i = 1.0f;
- double lasttime= PIL_check_seconds_timer();
+ double time, lasttime= PIL_check_seconds_timer();
const int res = ma->vol_precache_resolution;
+ /* create a raytree with just the faces of the instanced ObjectRen,
+ * used for checking if the cached point is inside or outside. */
+ RayTree *tree = create_raytree_obi(obi, bbmin, bbmax);
+ if (!tree) return;
+
+ /* Need a shadeinput to calculate scattering */
memset(&shi, 0, sizeof(ShadeInput));
shi.depth= 1;
shi.mask= 1;
@@ -707,18 +871,28 @@ void vol_precache_objectinstance(Render *re, ObjectInstanceRen *obi, Material *m
shi.har= shi.mat->har;
shi.obi= obi;
shi.obr= obi->obr;
+ shi.lay = re->scene->lay;
+ shi.re = re;
+ VECCOPY(shi.view, view);
stepsize = vol_get_stepsize(&shi, STEPSIZE_VIEW);
- resf = (float) res;
+ resf = (float)res;
res_2 = res*res;
res_3 = res*res*res;
+ res_3f = (float)res_3;
VecSubf(voxel, bbmax, bbmin);
VecMulf(voxel, 1.0f/res);
- obi->volume_precache = MEM_mallocN(sizeof(float)*res*res*res, "volume light cache");
+ obi->volume_precache = MEM_callocN(sizeof(float)*res_3*3, "volume light cache");
+ /* Iterate over the 3d voxel grid, and fill the voxels with scattering information
+ *
+ * It's stored in memory as 3 big float grids next to each other, one for each RGB channel.
+ * I'm guessing the memory alignment may work out better this way for the purposes
+ * of doing linear interpolation, but I haven't actually tested this theory! :)
+ */
for (x=0; x < res; x++) {
co[0] = bbmin[0] + (voxel[0] * x);
@@ -726,47 +900,54 @@ void vol_precache_objectinstance(Render *re, ObjectInstanceRen *obi, Material *m
co[1] = bbmin[1] + (voxel[1] * y);
for (z=0; z < res; z++) {
- double time= PIL_check_seconds_timer();
-
co[2] = bbmin[2] + (voxel[2] * z);
-
- density = vol_get_density(&shi, co);
- vol_get_scattering(re, &shi, scatter_col, co, stepsize, density);
- obi->volume_precache[x*res_2 + y*res + z] = (scatter_col[0] + scatter_col[1] + scatter_col[2]) / 3.0f;
-
+ time= PIL_check_seconds_timer();
+ i++;
+
/* display progress every second */
if(re->test_break())
return;
if(time-lasttime>1.0f) {
char str[64];
- sprintf(str, "Precaching volume: %d%%", (int)(100.0f * (i / res_3)));
+ sprintf(str, "Precaching volume: %d%%", (int)(100.0f * (i / res_3f)));
re->i.infostr= str;
re->stats_draw(&re->i);
re->i.infostr= NULL;
lasttime= time;
}
- i++;
+ /* don't bother if the point is not inside the volume mesh */
+ if (!point_inside_obi(tree, obi, co))
+ continue;
+
+ density = vol_get_density(&shi, co);
+ vol_get_scattering(&shi, scatter_col, co, stepsize, density);
+
+ obi->volume_precache[0*res_3 + x*res_2 + y*res + z] = scatter_col[0];
+ obi->volume_precache[1*res_3 + x*res_2 + y*res + z] = scatter_col[1];
+ obi->volume_precache[2*res_3 + x*res_2 + y*res + z] = scatter_col[2];
}
}
}
+
+ if(tree) {
+ RE_ray_tree_free(tree);
+ tree= NULL;
+ }
}
+/* loop through all objects (and their associated materials)
+ * marked for pre-caching in convertblender.c, and pre-cache them */
void volume_precache(Render *re)
{
ObjectInstanceRen *obi;
VolPrecache *vp;
- int i=1;
-
- printf("Precaching %d volumes... \n", BLI_countlist(&re->vol_precache_obs));
-
+
for(vp= re->vol_precache_obs.first; vp; vp= vp->next) {
for(obi= re->instancetable.first; obi; obi= obi->next) {
- if (obi->obr == vp->obr) {
- printf("Precaching Object: %s with Material: %s \n", vp->obr->ob->id.name+2, vp->ma->id.name+2);
+ if (obi->obr == vp->obr)
vol_precache_objectinstance(re, obi, vp->ma, obi->obr->boundbox[0], obi->obr->boundbox[1]);
- }
}
}
@@ -779,10 +960,8 @@ void free_volume_precache(Render *re)
ObjectInstanceRen *obi;
for(obi= re->instancetable.first; obi; obi= obi->next) {
- if (obi->volume_precache) {
+ if (obi->volume_precache)
MEM_freeN(obi->volume_precache);
- printf("freed volume precache of object: %s \n", obi->obr->ob->id.name+2);
- }
}
BLI_freelistN(&re->vol_precache_obs);
diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c
index 8ad4078b90e..72a396d63be 100644
--- a/source/blender/src/buttons_shading.c
+++ b/source/blender/src/buttons_shading.c
@@ -4357,7 +4357,7 @@ static void material_panel_material_volume(Material *ma)
short yco=PANEL_YMAX;
block= uiNewBlock(&curarea->uiblocks, "material_panel_material_volume", UI_EMBOSS, UI_HELV, curarea->win);
- if(uiNewPanel(curarea, block, "Volume", "Material", PANELX, PANELY, PANELW, PANELH)==0) return;
+ if(uiNewPanel(curarea, block, "Volume", "Material", PANELX, PANELY, PANELW, PANELH+40)==0) return;
uiSetButLock(ma->id.lib!=NULL, ERROR_LIBDATA_MESSAGE);
@@ -4365,32 +4365,28 @@ static void material_panel_material_volume(Material *ma)
uiDefButF(block, NUM, B_MATPRV, "Step Size: ",
X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_stepsize), 0.001, 100.0, 10, 2, "Ray marching step size");
uiDefButS(block, MENU, B_TEXREDR_PRV, "Step Size Calculation %t|Randomized %x0|Constant %x1",
- X2CLM1, yco-=BUTH, BUTW2, BUTH, &ma->vol_stepsize_type, 0.0, 0.0, 0, 0, "Step size calculation, replace banding with jittering");
+ X2CLM1, yco-=BUTH, BUTW2, BUTH, &ma->vol_stepsize_type, 0.0, 0.0, 0, 0, "Step size calculation, randomized replaces banding with jittering");
uiBlockEndAlign(block);
yco -= YSPACE;
-
+
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, MA_VOL_ATTENUATED, B_MATPRV, "Self Shading",
X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_shadeflag), 0, 0, 0, 0, "Uses absorption for light attenuation");
uiDefButF(block, NUM, B_MATPRV, "Step Size: ",
X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_shade_stepsize), 0.001, 100.0, 10, 2, "Step");
- uiDefButBitS(block, TOG, MA_VOL_PRECACHESHADING, B_MATPRV, "Precache",
- X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_shadeflag), 0, 0, 0, 0, "precache");
- uiDefButS(block, NUM, B_MATPRV, "Resolution: ",
- X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_precache_resolution), 0.0, 1024.0, 10, 2, "precache voxel resolution");
uiBlockEndAlign(block);
yco -= YSPACE;
- uiBlockBeginAlign(block);
- uiDefButS(block, MENU, B_TEXREDR_PRV, "Scattering Direction %t|Isotropic %x0|Mie Hazy %x1|Mie Murky %x2|Rayleigh %x3|Henyey-Greenstein %x4|Schlick %x5",
- X2CLM1, yco-=BUTH, BUTW2, BUTH, &ma->vol_phasefunc_type, 0.0, 0.0, 0, 0, "Scattering Direction (Phase Function)");
- if (ELEM(ma->vol_phasefunc_type, MA_VOL_PH_HG, MA_VOL_PH_SCHLICK)) {
- uiDefButF(block, NUM, B_MATPRV, "Asymmetry: ",
- X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_phasefunc_g), -1.0, 1.0, 0, 0, "> 0 is forward scattering, < 0 is back scattering");
+ if (ma->vol_shadeflag & MA_VOL_ATTENUATED) {
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, MA_VOL_PRECACHESHADING, B_MATPRV, "Light Cache",
+ X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_shadeflag), 0, 0, 0, 0, "Pre-cache the shading information into a voxel grid");
+ uiDefButS(block, NUM, B_MATPRV, "Resolution: ",
+ X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_precache_resolution), 0.0, 1024.0, 10, 2, "Resolution of the voxel grid, low resolutions are faster, high resolutions use more memory (res ^3)");
+ uiBlockEndAlign(block);
}
- uiBlockEndAlign(block);
/*uiDefButBitS(block, TOG, MA_VOL_RECVSHADOW, B_MATPRV, "Receive Shadows",
X2CLM1, yco-=BUTH, BUTW2, BUTH, &(ma->vol_shadeflag), 0, 0, 0, 0, "Receive shadows from external objects");
@@ -4409,7 +4405,7 @@ static void material_panel_material_volume(Material *ma)
uiBlockBeginAlign(block);
uiDefButF(block, NUM, B_MATPRV, "Absorption: ",
- X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->vol_absorption), 0.0, 100.0, 10, 0, "Multiplier for absorption");
+ X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->vol_absorption), 0.0, 100.0, 10, 0, "Amount of light absorbed by the volume");
uiDefButF(block, COL, B_MATPRV, "",
X2CLM2, yco-=BUTH, BUTW2, BUTH, ma->vol_absorption_col, 0, 0, 0, B_MATCOL, "");
uiBlockEndAlign(block);
@@ -4418,7 +4414,7 @@ static void material_panel_material_volume(Material *ma)
uiBlockBeginAlign(block);
uiDefButF(block, NUMSLI, B_MATPRV, "Emit: ",
- X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->emit), 0.0, 2.0, 0, 0, "Emission component");
+ X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->emit), 0.0, 2.0, 0, 0, "Amount of light emitted from the volume");
uiDefButF(block, COL, B_MATPRV, "",
X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->r), 0, 0, 0, B_MATCOL, "");
uiBlockEndAlign(block);
@@ -4426,7 +4422,24 @@ static void material_panel_material_volume(Material *ma)
yco -= YSPACE;
uiDefButF(block, NUM, B_MATPRV, "Scattering: ",
- X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->vol_scattering), 0.0, 100.0, 10, 0, "Multiplier for scattering");
+ X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->vol_scattering), 0.0, 100.0, 10, 0, "Amount of light scattered through the volume from lamps");
+
+ yco -= YSPACE;
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, MENU, B_TEXREDR_PRV, "Scattering Direction %t|Isotropic %x0|Mie Hazy %x1|Mie Murky %x2|Rayleigh %x3|Henyey-Greenstein %x4|Schlick %x5",
+ X2CLM2, yco-=BUTH, BUTW2, BUTH, &ma->vol_phasefunc_type, 0.0, 0.0, 0, 0, "Scattering Direction (Phase Function)");
+ if (ELEM(ma->vol_phasefunc_type, MA_VOL_PH_HG, MA_VOL_PH_SCHLICK)) {
+ uiDefButF(block, NUM, B_MATPRV, "Asymmetry: ",
+ X2CLM2, yco-=BUTH, BUTW2, BUTH, &(ma->vol_phasefunc_g), -1.0, 1.0, 0, 0, "> 0 is forward scattering, < 0 is back scattering");
+ uiBlockEndAlign(block);
+ } else {
+ uiBlockEndAlign(block);
+ /* spacer */
+ uiDefBut(block, LABEL, B_NOP, "",
+ X2CLM2, yco-=BUTH, BUTW2, BUTH, 0, 0, 0, 0, 0, "");
+ }
+
}
static void material_panel_nodes(Material *ma)