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:
authorMatt Ebb <matt@mke3.net>2008-12-13 08:41:34 +0300
committerMatt Ebb <matt@mke3.net>2008-12-13 08:41:34 +0300
commit92f5c719aedf79db7e45d3b887146a559321981e (patch)
tree877e8a5c91f19a17dcce8cc5d14f2dda00ef6e80 /source/blender/render
parentaef61a7000c279a96f1bb0e1fedf7da2574292fd (diff)
* Volume Rendering: Voxel data
This commit introduces a new texture ('Voxel Data'), used to load up saved voxel data sets for rendering, contributed by Raúl 'farsthary' Fernández Hernández with some additional tweaks. Thanks, Raúl! The texture works similar to the existing point density texture, currently it only provides intensity information, which can then be mapped (for example) to density in a volume material. This is an early version, intended to read the voxel format saved by Raúl's command line simulators, in future revisions there's potential for making a more full-featured 'Blender voxel file format', and also for supporting other formats too. Note: Due to some subtleties in Raúl's existing released simulators, in order to load them correctly the voxel data texture, you'll need to raise the 'resolution' value by 2. So if you baked out the simulation at resolution 50, enter 52 for the resolution in the texture panel. This can possibly be fixed in the simulator later on. Right now, the way the texture is mapped is just in the space 0,0,0 <-> 1,1,1 and it can appear rotated 90 degrees incorrectly. This will be tackled, for now, probably the easiest way to map it is with and empty, using Map Input -> Object. Smoke test: http://www.vimeo.com/2449270 One more note, trilinear interpolation seems a bit slow at the moment, we'll look into this. For curiosity, while testing/debugging this, I made a script that exports a mesh to voxel data. Here's a test of grogan (www.kajimba.com) converted to voxels, rendered as a volume: http://www.vimeo.com/2512028 The script is available here: http://mke3.net/projects/bpython/export_object_voxeldata.py * Another smaller thing, brought back early ray termination (was disabled previously for debugging) and made it user configurable. It now appears as a new value in the volume material: 'Depth Cutoff'. For some background info on what this does, check: http://farsthary.wordpress.com/2008/12/11/cutting-down-render-times/ * Also some disabled work-in-progess code for light cache
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/intern/include/render_types.h14
-rw-r--r--source/blender/render/intern/include/volume_precache.h3
-rw-r--r--source/blender/render/intern/source/convertblender.c61
-rw-r--r--source/blender/render/intern/source/texture.c5
-rw-r--r--source/blender/render/intern/source/volume_precache.c98
-rw-r--r--source/blender/render/intern/source/volumetric.c16
6 files changed, 143 insertions, 54 deletions
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 6f4537d84fb..65bb12e059d 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -203,6 +203,8 @@ struct Render
struct Object *excludeob;
ListBase vol_precache_obs;
+ ListBase render_volumes_inside;
+ ListBase volumes;
/* arena for allocating data for use during render, for
* example dynamic TFaces to go in the VlakRen structure.
@@ -409,6 +411,18 @@ typedef struct VolPrecache
struct ObjectRen *obr;
} VolPrecache;
+typedef struct VolumeOb
+{
+ struct VolumeOb *next, *prev;
+ struct Material *ma;
+ struct ObjectRen *obr;
+} VolumeOb;
+
+typedef struct MatInside {
+ struct MatInside *next, *prev;
+ struct Material *ma;
+} MatInside;
+
/* ------------------------------------------------------------------------- */
struct LampRen;
diff --git a/source/blender/render/intern/include/volume_precache.h b/source/blender/render/intern/include/volume_precache.h
index 7a719840f48..78409e4c646 100644
--- a/source/blender/render/intern/include/volume_precache.h
+++ b/source/blender/render/intern/include/volume_precache.h
@@ -27,4 +27,5 @@
*/
void volume_precache(Render *re);
-void free_volume_precache(Render *re); \ No newline at end of file
+void free_volume_precache(Render *re);
+int point_inside_volume_objectinstance(ObjectInstanceRen *obi, float *co); \ No newline at end of file
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 09f2d1275f4..d87ee65c42c 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -104,6 +104,7 @@
#include "multires.h"
#include "occlusion.h"
#include "pointdensity.h"
+#include "voxeldata.h"
#include "render_types.h"
#include "rendercore.h"
#include "renderdatabase.h"
@@ -3028,16 +3029,51 @@ static void use_mesh_edge_lookup(ObjectRen *obr, DerivedMesh *dm, MEdge *medge,
}
}
-static void add_vol_precache(Render *re, ObjectRen *obr, Material *ma)
+static void free_camera_inside_volumes(Render *re)
{
- struct VolPrecache *vp;
+ BLI_freelistN(&re->render_volumes_inside);
+}
+
+static void init_camera_inside_volumes(Render *re)
+{
+ ObjectInstanceRen *obi;
+ VolumeOb *vo;
+ float co[3] = {0.f, 0.f, 0.f};
+
+ for(vo= re->volumes.first; vo; vo= vo->next) {
+ for(obi= re->instancetable.first; obi; obi= obi->next) {
+ if (obi->obr == vo->obr) {
+ if (point_inside_volume_objectinstance(obi, co)) {
+ MatInside *mi;
+
+ mi = MEM_mallocN(sizeof(MatInside), "camera inside material");
+ mi->ma = vo->ma;
+
+ BLI_addtail(&(re->render_volumes_inside), mi);
+ }
+ }
+ }
+ }
+
+ {
+ MatInside *m;
+ for (m=re->render_volumes_inside.first; m; m=m->next) {
+ printf("matinside: ma: %s \n", m->ma->id.name+2);
+ }
- vp = MEM_mallocN(sizeof(VolPrecache), "volume precache object");
+ }
+}
+
+static void add_volume(Render *re, ObjectRen *obr, Material *ma)
+{
+ struct VolumeOb *vo;
- vp->ma = ma;
- vp->obr = obr;
+ vo = MEM_mallocN(sizeof(VolumeOb), "volume object");
- BLI_addtail(&re->vol_precache_obs, vp);
+ vo->ma = ma;
+ vo->obr = obr;
+
+ BLI_addtail(&re->volumes, vo);
}
static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
@@ -3095,9 +3131,8 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
if(ma->mode & MA_RADIO)
do_autosmooth= 1;
- if ((ma->material_type == MA_VOLUME) && (ma->vol_shadeflag & MA_VOL_PRECACHESHADING)) {
- add_vol_precache(re, obr, ma);
- }
+ if (ma->material_type == MA_VOLUME)
+ add_volume(re, obr, ma);
}
}
@@ -4457,6 +4492,9 @@ void RE_Database_Free(Render *re)
end_render_textures();
free_pointdensities(re);
+ free_voxeldata(re);
+
+ free_camera_inside_volumes(re);
if(re->wrld.aosphere) {
MEM_freeN(re->wrld.aosphere);
@@ -4861,6 +4899,8 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
/* MAKE RENDER DATA */
database_init_objects(re, lay, 0, 0, 0, 0);
+
+ init_camera_inside_volumes(re);
if(!re->test_break()) {
int tothalo;
@@ -4912,6 +4952,9 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
/* point density texture */
if(!re->test_break())
make_pointdensities(re);
+ /* voxel data texture */
+ if(!re->test_break())
+ make_voxeldata(re);//Volumetrics
}
if(!re->test_break())
diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c
index d7d4d124b18..d7b41d7cc2c 100644
--- a/source/blender/render/intern/source/texture.c
+++ b/source/blender/render/intern/source/texture.c
@@ -65,6 +65,7 @@
#include "envmap.h"
#include "pointdensity.h"
+#include "voxeldata.h"
#include "renderpipeline.h"
#include "render_types.h"
#include "rendercore.h"
@@ -1257,6 +1258,10 @@ static int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex,
case TEX_POINTDENSITY:
retval= pointdensitytex(tex, texvec, texres);
break;
+ case TEX_VOXELDATA:
+ retval= voxeldatatex(tex, texvec, texres);
+ break;
+
}
if (tex->flag & TEX_COLORBAND) {
diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c
index 246f9bc6d69..89f997f4b99 100644
--- a/source/blender/render/intern/source/volume_precache.c
+++ b/source/blender/render/intern/source/volume_precache.c
@@ -400,7 +400,7 @@ static void *vol_precache_part(void *data)
return 0;
}
-void precache_setup_shadeinput(Render *re, ObjectInstanceRen *obi, Material *ma, ShadeInput *shi)
+static void precache_setup_shadeinput(Render *re, ObjectInstanceRen *obi, Material *ma, ShadeInput *shi)
{
float view[3] = {0.0,0.0,-1.0};
@@ -417,6 +417,34 @@ void precache_setup_shadeinput(Render *re, ObjectInstanceRen *obi, Material *ma,
VECCOPY(shi->view, view);
}
+static void precache_init_parts(ListBase *precache_parts, RayTree *tree, ShadeInput *shi, ObjectInstanceRen *obi, float *bbmin, float *bbmax, int res)
+{
+ int i;
+ float voxel[3];
+
+ VecSubf(voxel, bbmax, bbmin);
+ if ((voxel[0] < FLT_EPSILON) || (voxel[1] < FLT_EPSILON) || (voxel[2] < FLT_EPSILON))
+ return;
+ VecMulf(voxel, 1.0f/res);
+
+ for(i=0; i < totparts; i++) {
+ VolPrecachePart *pa= MEM_callocN(sizeof(VolPrecachePart), "new precache part");
+
+ pa->done = 0;
+ pa->num = i;
+
+ pa->res = res;
+ VECCOPY(pa->bbmin, bbmin);
+ VECCOPY(precache_parts[j].voxel, voxel);
+ precache_parts[j].tree = tree;
+ precache_parts[j].shi = shi;
+ precache_parts[j].obi = obi;
+
+ BLI_addtail(precache_parts, pa);
+ }
+
+}
+
void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Material *ma, float *bbmin, float *bbmax)
{
int x, y, z;
@@ -431,13 +459,12 @@ void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Mat
int res_2, res_3;
int edgeparts=2;
- int totparts;
- ListBase threads;
+ ListBase threads, precache_parts;
int cont= 1;
int xparts, yparts, zparts;
float part[3];
int totthread = re->r.threads;
- ListBase precache_parts;
+ int totparts = edgeparts*edgeparts*edgeparts;
VolPrecachePart *nextpa;
int j;
@@ -452,41 +479,13 @@ void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Mat
* used for checking if the cached point is inside or outside. */
tree = create_raytree_obi(obi, bbmin, bbmax);
if (!tree) return;
-
- /* Need a shadeinput to calculate scattering */
- precache_setup_shadeinput(re, obi, ma, &shi);
-
- VecSubf(voxel, bbmax, bbmin);
- if ((voxel[0] < FLT_EPSILON) || (voxel[1] < FLT_EPSILON) || (voxel[2] < FLT_EPSILON))
- return;
- VecMulf(voxel, 1.0f/res);
-
- part[0] = ceil(res/(float)xparts);
- part[1] = ceil(res/(float)yparts);
- part[2] = ceil(res/(float)zparts);
obi->volume_precache = MEM_callocN(sizeof(float)*res_3*3, "volume light cache");
-
- totparts = edgeparts*edgeparts*edgeparts;
- precache_parts= MEM_callocN(sizeof(VolPrecachePart)*totparts, "VolPrecachePart");
- memset(precache_parts, 0, sizeof(VolPrecachePart)*totparts);
- precache_init_parts(precache_parts);
+ /* Need a shadeinput to calculate scattering */
+ precache_setup_shadeinput(re, obi, ma, &shi);
+ precache_init_parts(&precache_parts, tree, shi, obi, bbmin, bbmax, res);
- for(j=0; j < totparts; j++) {
- VolPrecachePart *pa= MEM_callocN(sizeof(VolPrecachePart), "new precache part");
-
- pa->done = 0;
- pa->num = j;
-
- pa->res = res;
- VECCOPY(pa->bbmin, bbmin);
- VECCOPY(precache_parts[j].voxel, voxel);
- precache_parts[j].tree = tree;
- precache_parts[j].shi = shi;
- precache_parts[j].obi = obi;
- }
-
BLI_init_threads(&threads, vol_precache_part, totthread);
nextpa = precache_get_new_part(precache_threads);
@@ -600,12 +599,15 @@ void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Mat
void volume_precache(Render *re)
{
ObjectInstanceRen *obi;
- VolPrecache *vp;
+ VolumeOb *vo;
- 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)
- vol_precache_objectinstance(re, obi, vp->ma, obi->obr->boundbox[0], obi->obr->boundbox[1]);
+ for(vo= re->volumes.first; vo; vo= vo->next) {
+ if (vo->ma->vol_shadeflag & MA_VOL_PRECACHESHADING) {
+ for(obi= re->instancetable.first; obi; obi= obi->next) {
+ if (obi->obr == vo->obr) {
+ vol_precache_objectinstance(re, obi, vo->ma, obi->obr->boundbox[0], obi->obr->boundbox[1]);
+ }
+ }
}
}
@@ -624,3 +626,19 @@ void free_volume_precache(Render *re)
BLI_freelistN(&re->vol_precache_obs);
}
+
+int point_inside_volume_objectinstance(ObjectInstanceRen *obi, float *co)
+{
+ RayTree *tree;
+ int inside=0;
+
+ tree = create_raytree_obi(obi, obi->obr->boundbox[0], obi->obr->boundbox[1]);
+ if (!tree) return 0;
+
+ inside = point_inside_obi(tree, obi, co);
+
+ RE_ray_tree_free(tree);
+ tree= NULL;
+
+ return inside;
+}
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
index 45d54d40fa1..fba847da2ad 100644
--- a/source/blender/render/intern/source/volumetric.c
+++ b/source/blender/render/intern/source/volumetric.c
@@ -21,7 +21,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): Matt Ebb, Raul Hernandez.
+ * Contributor(s): Matt Ebb, Raul Fernandez Hernandez (Farsthary)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -134,6 +134,11 @@ float vol_get_stepsize(struct ShadeInput *shi, int context)
return shi->mat->vol_stepsize;
}
+static float vol_get_depth_cutoff(struct ShadeInput *shi)
+{
+ return shi->mat->vol_depth_cutoff;
+}
+
/* SHADING */
static float D(ShadeInput *shi, int rgb, int x, int y, int z)
@@ -278,7 +283,7 @@ float vol_get_phasefunc(ShadeInput *shi, short phasefunc_type, float g, float *w
void vol_get_absorption(ShadeInput *shi, float *absorb_col, float *co)
{
float dummy = 1.0f;
- float absorption = shi->mat->vol_absorption;
+ const float absorption = shi->mat->vol_absorption;
VECCOPY(absorb_col, shi->mat->vol_absorption_col);
@@ -296,14 +301,13 @@ void vol_get_absorption(ShadeInput *shi, float *absorb_col, float *co)
void vol_get_attenuation(ShadeInput *shi, float *tau, float *co, float *endco, float density, float stepsize)
{
/* input density = density at co */
- float dist;
float absorb_col[3];
int s, nsteps;
float step_vec[3], step_sta[3], step_end[3];
+ const float dist = VecLenf(co, endco);
vol_get_absorption(shi, absorb_col, co);
- dist = VecLenf(co, endco);
nsteps = (int)((dist / stepsize) + 0.5);
/* trigger for recalculating density */
@@ -468,6 +472,7 @@ static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float
float tau[3], 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 = vol_get_density(shi, co);
+ const float depth_cutoff = vol_get_depth_cutoff(shi);
/* multiply col_behind with beam transmittance over entire distance */
vol_get_attenuation(shi, tau, co, endco, density, stepsize);
@@ -524,6 +529,9 @@ static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float
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;
}
VecCopyf(col, radiance);