diff options
18 files changed, 395 insertions, 283 deletions
diff --git a/release/scripts/ui/buttons_material.py b/release/scripts/ui/buttons_material.py index 448cb36e130..ee7193da301 100644 --- a/release/scripts/ui/buttons_material.py +++ b/release/scripts/ui/buttons_material.py @@ -609,6 +609,23 @@ class VolumeButtonsPanel(bpy.types.Panel): mat = context.material engine = context.scene.render_data.engine return mat and (mat.type == 'VOLUME') and (engine in self.COMPAT_ENGINES) + +class MATERIAL_PT_volume_density(VolumeButtonsPanel): + __label__ = "Density" + __default_closed__ = False + COMPAT_ENGINES = set(['BLENDER_RENDER']) + + def draw(self, context): + layout = self.layout + + mat = context.material + vol = context.material.volume + + split = layout.split() + row = split.row() + row.itemR(vol, "density") + row.itemR(vol, "density_scale") + class MATERIAL_PT_volume_shading(VolumeButtonsPanel): __label__ = "Shading" @@ -620,22 +637,23 @@ class MATERIAL_PT_volume_shading(VolumeButtonsPanel): vol = context.material.volume - row = layout.row() - row.itemR(vol, "density") - row.itemR(vol, "scattering") - split = layout.split() col = split.column() - col.itemR(vol, "absorption") - col.itemR(vol, "absorption_color", text="") - + col.itemR(vol, "scattering") + col.itemR(vol, "asymmetry") + col.itemR(vol, "transmission_color") + col = split.column() - col.itemR(vol, "emission") - col.itemR(vol, "emission_color", text="") + sub = col.column(align=True) + sub.itemR(vol, "emission") + sub.itemR(vol, "emission_color", text="") + sub = col.column(align=True) + sub.itemR(vol, "reflection") + sub.itemR(vol, "reflection_color", text="") -class MATERIAL_PT_volume_scattering(VolumeButtonsPanel): - __label__ = "Scattering" +class MATERIAL_PT_volume_lighting(VolumeButtonsPanel): + __label__ = "Lighting" __default_closed__ = False COMPAT_ENGINES = set(['BLENDER_RENDER']) @@ -648,24 +666,26 @@ class MATERIAL_PT_volume_scattering(VolumeButtonsPanel): col = split.column() col.itemR(vol, "scattering_mode", text="") + + col = split.column() + if vol.scattering_mode == 'SINGLE_SCATTERING': col.itemR(vol, "light_cache") sub = col.column() sub.active = vol.light_cache sub.itemR(vol, "cache_resolution") elif vol.scattering_mode in ('MULTIPLE_SCATTERING', 'SINGLE_PLUS_MULTIPLE_SCATTERING'): + sub = col.column() + sub.enabled = True + sub.active = False + sub.itemR(vol, "light_cache") col.itemR(vol, "cache_resolution") sub = col.column(align=True) sub.itemR(vol, "ms_diffusion") sub.itemR(vol, "ms_spread") sub.itemR(vol, "ms_intensity") - - col = split.column() - # col.itemL(text="Anisotropic Scattering:") - col.itemR(vol, "phase_function", text="") - if vol.phase_function in ('SCHLICK', 'HENYEY-GREENSTEIN'): - col.itemR(vol, "asymmetry") + class MATERIAL_PT_volume_transp(VolumeButtonsPanel): __label__= "Transparency" @@ -693,16 +713,15 @@ class MATERIAL_PT_volume_integration(VolumeButtonsPanel): col = split.column() col.itemL(text="Step Calculation:") col.itemR(vol, "step_calculation", text="") - sub = col.column(align=True) - sub.itemR(vol, "step_size") - sub.itemR(vol, "shading_step_size") + col = col.column(align=True) + col.itemR(vol, "step_size") col = split.column() col.itemL() col.itemR(vol, "depth_cutoff") - col.itemR(vol, "density_scale") +bpy.types.register(MATERIAL_PT_volume_density) bpy.types.register(MATERIAL_PT_volume_shading) -bpy.types.register(MATERIAL_PT_volume_scattering) +bpy.types.register(MATERIAL_PT_volume_lighting) bpy.types.register(MATERIAL_PT_volume_transp) bpy.types.register(MATERIAL_PT_volume_integration) diff --git a/release/scripts/ui/buttons_texture.py b/release/scripts/ui/buttons_texture.py index c95fa266aaa..9765aa93ca4 100644 --- a/release/scripts/ui/buttons_texture.py +++ b/release/scripts/ui/buttons_texture.py @@ -246,13 +246,14 @@ class TEXTURE_PT_influence(TextureSlotPanel): col = split.column() factor_but(col, tex.map_density, "map_density", "density_factor", "Density") factor_but(col, tex.map_emission, "map_emission", "emission_factor", "Emission") - factor_but(col, tex.map_absorption, "map_absorption", "absorption_factor", "Absorption") factor_but(col, tex.map_scattering, "map_scattering", "scattering_factor", "Scattering") + factor_but(col, tex.map_reflection, "map_reflection", "reflection_factor", "Reflection") col = split.column() col.itemL(text=" ") factor_but(col, tex.map_alpha, "map_coloremission", "coloremission_factor", "Emission Color") - factor_but(col, tex.map_colorabsorption, "map_colorabsorption", "colorabsorption_factor", "Absorption Color") + factor_but(col, tex.map_colortransmission, "map_colortransmission", "colortransmission_factor", "Transmission Color") + factor_but(col, tex.map_colorreflection, "map_colorreflection", "colorreflection_factor", "Reflection Color") elif la: row = layout.row() @@ -642,6 +643,7 @@ class TEXTURE_PT_voxeldata(TextureButtonsPanel): row.itemR(vd, "still_frame_number") layout.itemR(vd, "interpolation") + layout.itemR(vd, "extension") layout.itemR(vd, "intensity") class TEXTURE_PT_pointdensity(TextureButtonsPanel): diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 1667bd97102..cbd306f6d87 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -172,15 +172,15 @@ void init_material(Material *ma) ma->vol.density = 1.0f; ma->vol.emission = 0.0f; - ma->vol.absorption = 1.0f; ma->vol.scattering = 1.0f; + ma->vol.reflection = 1.0f; + ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f; + ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f; ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f; - ma->vol.absorption_col[0] = ma->vol.absorption_col[1] = ma->vol.absorption_col[2] = 0.0f; ma->vol.density_scale = 1.0f; ma->vol.depth_cutoff = 0.01f; ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED; ma->vol.stepsize = 0.2f; - ma->vol.shade_stepsize = 0.2f; ma->vol.shade_type = MA_VOL_SHADE_SINGLE; ma->vol.shadeflag |= MA_VOL_PRECACHESHADING; ma->vol.precache_resolution = 50; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index d7616ec8a9a..287396a85c8 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -984,6 +984,7 @@ struct VoxelData *BKE_add_voxeldata(void) vd->interp_type= TEX_VD_LINEAR; vd->file_format= TEX_VD_SMOKE; vd->int_multiplier = 1.0; + vd->extend = TEX_CLIP; vd->object = NULL; return vd; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 114ec9095b1..94478b0d235 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9573,15 +9573,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if (ma->vol.stepsize < 0.0001f) { ma->vol.density = 1.0f; ma->vol.emission = 0.0f; - ma->vol.absorption = 1.0f; ma->vol.scattering = 1.0f; ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f; - ma->vol.absorption_col[0] = ma->vol.absorption_col[1] = ma->vol.absorption_col[2] = 0.0f; ma->vol.density_scale = 1.0f; ma->vol.depth_cutoff = 0.01f; ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED; ma->vol.stepsize = 0.2f; - ma->vol.shade_stepsize = 0.2f; ma->vol.shade_type = MA_VOL_SHADE_SINGLE; ma->vol.shadeflag |= MA_VOL_PRECACHESHADING; ma->vol.precache_resolution = 50; @@ -9703,6 +9700,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main) { Scene *sce; Object *ob; + Material *ma; + Tex *tex; for(sce = main->scene.first; sce; sce = sce->id.next) if(sce->unit.scale_length == 0.0f) @@ -9716,7 +9715,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main) /* rotation modes were added, but old objects would now default to being 'quaternion based' */ ob->rotmode= ROT_MODE_EUL; } + + for (ma = main->mat.first; ma; ma=ma->id.next) { + if (ma->vol.reflection == 0.f) { + ma->vol.reflection = 1.f; + ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f; + ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f; + } + } + for (tex = main->tex.first; tex; tex=tex->id.next) { + if (tex->vd) { + if (tex->vd->extend == 0) tex->vd->extend = TEX_CLIP; + } + } + for(sce= main->scene.first; sce; sce= sce->id.next) { if(sce->audio.main == 0.0) diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 81f6badc24b..7dc04a47c51 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -334,6 +334,19 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre } } } + + /* turn off bounce lights for volume, + * doesn't make much visual difference and slows it down too */ + if(mat->material_type == MA_TYPE_VOLUME) { + for(base= sce->base.first; base; base= base->next) { + if(base->object->type == OB_LAMP) { + /* if doesn't match 'Lamp.002' --> main key light */ + if( strcmp(base->object->id.name+2, "Lamp.002") != 0 ) { + base->object->restrictflag |= OB_RESTRICT_RENDER; + } + } + } + } if(sp->pr_method==PR_ICON_RENDER) { @@ -363,6 +376,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre if(matar && actcol < base->object->totcol) (*matar)[actcol]= mat; + } else if (base->object->type == OB_LAMP) { + base->object->restrictflag &= ~OB_RESTRICT_RENDER; } } } diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 55e3c9107e4..b3a7e74e91d 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -50,26 +50,23 @@ struct Ipo; typedef struct VolumeSettings { float density; float emission; - float absorption; float scattering; + float reflection; float emission_col[3]; - float absorption_col[3]; + float transmission_col[3]; + float reflection_col[3]; + float density_scale; float depth_cutoff; - - short phasefunc_type; - short vpad[3]; - float phasefunc_g; - - float stepsize; - float shade_stepsize; + float asymmetry; short stepsize_type; short shadeflag; short shade_type; short precache_resolution; - + + float stepsize; float ms_diff; float ms_intensity; int ms_steps; @@ -160,9 +157,8 @@ typedef struct Material { float sss_front, sss_back; short sss_flag, sss_preset; - /* yafray: absorption color, dispersion parameters and material preset menu */ - float YF_ar, YF_ag, YF_ab, YF_dscale, YF_dpwr; - int YF_dsmp, YF_preset, YF_djit; + int mapto_textured; /* render-time cache to optimise texture lookups */ + int pad4; ListBase gpumaterial; /* runtime */ } Material; @@ -320,12 +316,14 @@ typedef struct Material { #define MAP_LAYER 16384 /* volume mapto - reuse definitions for now - a bit naughty! */ -#define MAP_DENSITY 128 -#define MAP_EMISSION 64 -#define MAP_EMISSION_COL 1 -#define MAP_ABSORPTION 512 -#define MAP_ABSORPTION_COL 8 -#define MAP_SCATTERING 16 +#define MAP_DENSITY 128 +#define MAP_EMISSION 64 +#define MAP_EMISSION_COL 1 +#define MAP_SCATTERING 16 +#define MAP_TRANSMISSION_COL 8 +#define MAP_REFLECTION_COL 4 +#define MAP_REFLECTION 32 + /* mapto for halo */ //#define MAP_HA_COL 1 @@ -386,13 +384,5 @@ typedef struct Material { #define MA_VOL_SHADE_MULTIPLE 2 #define MA_VOL_SHADE_SINGLEPLUSMULTIPLE 3 -/* vol_phasefunc_type */ -#define MA_VOL_PH_ISOTROPIC 0 -#define MA_VOL_PH_MIEHAZY 1 -#define MA_VOL_PH_MIEMURKY 2 -#define MA_VOL_PH_RAYLEIGH 3 -#define MA_VOL_PH_HG 4 -#define MA_VOL_PH_SCHLICK 5 - #endif diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index c13c0522004..c8f35b4306f 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -167,7 +167,8 @@ typedef struct VoxelData { int interp_type; short file_format; short flag; - int pad; + short extend; + short pad; struct Object *object; /* for rendering smoke sims */ float int_multiplier; diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 9f7b97dfa05..593fc2e5935 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -537,14 +537,19 @@ static void rna_def_material_mtex(BlenderRNA *brna) /* volume material */ prop= RNA_def_property(srna, "map_coloremission", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_EMISSION_COL); - RNA_def_property_ui_text(prop, "Emission Color", "Causes the texture to affect the colour of emission"); + RNA_def_property_ui_text(prop, "Emission Color", "Causes the texture to affect the color of emission"); RNA_def_property_update(prop, 0, "rna_Material_update"); - prop= RNA_def_property(srna, "map_colorabsorption", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_ABSORPTION_COL); - RNA_def_property_ui_text(prop, "Absorption Color", "Causes the texture to affect the result colour after absorption"); + prop= RNA_def_property(srna, "map_colorreflection", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_REFLECTION_COL); + RNA_def_property_ui_text(prop, "Reflection Color", "Causes the texture to affect the color of scattered light"); RNA_def_property_update(prop, 0, "rna_Material_update"); + prop= RNA_def_property(srna, "map_colortransmission", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_TRANSMISSION_COL); + RNA_def_property_ui_text(prop, "Transmission Color", "Causes the texture to affect the result color after other light has been scattered/absorbed"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); + prop= RNA_def_property(srna, "map_density", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_DENSITY); RNA_def_property_ui_text(prop, "Density", "Causes the texture to affect the volume's density"); @@ -555,28 +560,34 @@ static void rna_def_material_mtex(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Emission", "Causes the texture to affect the volume's emission"); RNA_def_property_update(prop, 0, "rna_Material_update"); - prop= RNA_def_property(srna, "map_absorption", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_ABSORPTION); - RNA_def_property_ui_text(prop, "Absorption", "Causes the texture to affect the volume's absorption"); - RNA_def_property_update(prop, 0, "rna_Material_update"); - prop= RNA_def_property(srna, "map_scattering", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_SCATTERING); RNA_def_property_ui_text(prop, "Scattering", "Causes the texture to affect the volume's scattering"); RNA_def_property_update(prop, 0, "rna_Material_update"); + prop= RNA_def_property(srna, "map_reflection", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mapto", MAP_REFLECTION); + RNA_def_property_ui_text(prop, "Reflection", "Causes the texture to affect the reflected light's brightness"); + RNA_def_property_update(prop, NC_TEXTURE, NULL); + prop= RNA_def_property(srna, "coloremission_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "colfac"); RNA_def_property_ui_range(prop, 0, 1, 10, 3); RNA_def_property_ui_text(prop, "Emission Color Factor", "Amount texture affects emission color."); RNA_def_property_update(prop, 0, "rna_Material_update"); - prop= RNA_def_property(srna, "colorabsorption_factor", PROP_FLOAT, PROP_NONE); + prop= RNA_def_property(srna, "colorreflection_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "colfac"); RNA_def_property_ui_range(prop, 0, 1, 10, 3); - RNA_def_property_ui_text(prop, "Absorpion Color Factor", "Amount texture affects diffuse color."); + RNA_def_property_ui_text(prop, "Reflection Color Factor", "Amount texture affects color of out-scattered light"); RNA_def_property_update(prop, 0, "rna_Material_update"); + prop= RNA_def_property(srna, "colortransmission_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "colfac"); + RNA_def_property_ui_range(prop, 0, 1, 10, 3); + RNA_def_property_ui_text(prop, "Transmission Color Factor", "Amount texture affects result color after light has been scattered/absorbed."); + RNA_def_property_update(prop, NC_TEXTURE, NULL); + prop= RNA_def_property(srna, "density_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "varfac"); RNA_def_property_ui_range(prop, 0, 1, 10, 3); @@ -589,16 +600,16 @@ static void rna_def_material_mtex(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Emission Factor", "Amount texture affects emission."); RNA_def_property_update(prop, 0, "rna_Material_update"); - prop= RNA_def_property(srna, "absorption_factor", PROP_FLOAT, PROP_NONE); + prop= RNA_def_property(srna, "scattering_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "varfac"); RNA_def_property_ui_range(prop, 0, 1, 10, 3); - RNA_def_property_ui_text(prop, "Absorption Factor", "Amount texture affects absorption."); + RNA_def_property_ui_text(prop, "Scattering Factor", "Amount texture affects scattering."); RNA_def_property_update(prop, 0, "rna_Material_update"); - - prop= RNA_def_property(srna, "scattering_factor", PROP_FLOAT, PROP_NONE); + + prop= RNA_def_property(srna, "reflection_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "varfac"); RNA_def_property_ui_range(prop, 0, 1, 10, 3); - RNA_def_property_ui_text(prop, "Scattering Factor", "Amount texture affects scattering."); + RNA_def_property_ui_text(prop, "Reflection Factor", "Amount texture affects brightness of out-scattered light."); RNA_def_property_update(prop, 0, "rna_Material_update"); /* end volume material */ @@ -955,15 +966,6 @@ static void rna_def_material_volume(BlenderRNA *brna) //{MA_VOL_STEP_ADAPTIVE, "ADAPTIVE", 0, "Adaptive", ""}, {0, NULL, 0, NULL, NULL}}; - static EnumPropertyItem prop_phasefunction_items[] = { - {MA_VOL_PH_ISOTROPIC, "ISOTROPIC", 0, "Isotropic", ""}, - {MA_VOL_PH_MIEHAZY, "MIE_HAZY", 0, "Mie Hazy", ""}, - {MA_VOL_PH_MIEMURKY, "MIE_MURKY", 0, "Mie Murky", ""}, - {MA_VOL_PH_RAYLEIGH, "RAYLEIGH", 0, "Rayleigh", ""}, - {MA_VOL_PH_HG, "HENYEY-GREENSTEIN", 0, "Henyey-Greenstein", ""}, - {MA_VOL_PH_SCHLICK, "SCHLICK", 0, "Schlick", ""}, - {0, NULL, 0, NULL, NULL}}; - srna= RNA_def_struct(brna, "MaterialVolume", NULL); RNA_def_struct_sdna(srna, "VolumeSettings"); RNA_def_struct_nested(brna, srna, "Material"); @@ -982,13 +984,6 @@ static void rna_def_material_volume(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Step Size", "Distance between subsequent volume depth samples."); RNA_def_property_update(prop, 0, "rna_Material_update"); - prop= RNA_def_property(srna, "shading_step_size", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "shade_stepsize"); - RNA_def_property_range(prop, 0.0f, FLT_MAX); - RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3); - RNA_def_property_ui_text(prop, "Shading Step Size", "Distance between subsequent volume shading samples."); - RNA_def_property_update(prop, 0, "rna_Material_update"); - prop= RNA_def_property(srna, "scattering_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "shade_type"); RNA_def_property_enum_items(prop, prop_scattering_items); @@ -1043,31 +1038,30 @@ static void rna_def_material_volume(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Density Scale", "Multiplier for the material's density"); RNA_def_property_update(prop, 0, "rna_Material_update"); - prop= RNA_def_property(srna, "absorption", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "absorption"); + prop= RNA_def_property(srna, "scattering", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "scattering"); RNA_def_property_range(prop, 0.0f, FLT_MAX); - RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3); - RNA_def_property_ui_text(prop, "Absorption", "Amount of light that gets absorbed by the volume - higher values mean light travels less distance"); + RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1 ,3); + RNA_def_property_ui_text(prop, "Scattering", "Amount of light that gets scattered out by the volume - the more out-scattering, the shallower the light will penetrate "); RNA_def_property_update(prop, 0, "rna_Material_update"); - prop= RNA_def_property(srna, "absorption_color", PROP_FLOAT, PROP_COLOR); - RNA_def_property_float_sdna(prop, NULL, "absorption_col"); + prop= RNA_def_property(srna, "transmission_color", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "transmission_col"); RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Absorption Color", ""); + RNA_def_property_ui_text(prop, "Transmission Color", "Result color of the volume, after other light has been scattered/absorbed"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); - prop= RNA_def_property(srna, "scattering", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "scattering"); - RNA_def_property_range(prop, 0.0f, FLT_MAX); - RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1 ,3); - RNA_def_property_ui_text(prop, "Scattering", "Amount of light that gets scattered by the volume - values > 1.0 are non-physical"); - RNA_def_property_update(prop, 0, "rna_Material_update"); + prop= RNA_def_property(srna, "reflection_color", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "reflection_col"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Reflection Color", "Colour of light scattered out of the volume (does not affect transmission)"); + RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING_DRAW, NULL); - prop= RNA_def_property(srna, "emission", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "emission"); + prop= RNA_def_property(srna, "reflection", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "reflection"); RNA_def_property_range(prop, 0.0f, FLT_MAX); - RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3); - RNA_def_property_ui_text(prop, "Emission", "Amount of light that gets emitted by the volume"); + RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1 ,3); + RNA_def_property_ui_text(prop, "Reflection", "Multiplier to make out-scattered light brighter or darker (non-physically correct)"); RNA_def_property_update(prop, 0, "rna_Material_update"); prop= RNA_def_property(srna, "emission_color", PROP_FLOAT, PROP_COLOR); @@ -1076,16 +1070,17 @@ static void rna_def_material_volume(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Emission Color", ""); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); - prop= RNA_def_property(srna, "phase_function", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "phasefunc_type"); - RNA_def_property_enum_items(prop, prop_phasefunction_items); - RNA_def_property_ui_text(prop, "Phase Function", "Isotropic/Anisotropic scattering"); + prop= RNA_def_property(srna, "emission", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "emission"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3); + RNA_def_property_ui_text(prop, "Emission", "Amount of light that gets emitted by the volume"); RNA_def_property_update(prop, 0, "rna_Material_update"); - + prop= RNA_def_property(srna, "asymmetry", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "phasefunc_g"); + RNA_def_property_float_sdna(prop, NULL, "asymmetry"); RNA_def_property_range(prop, -1.0f, 1.0f); - RNA_def_property_ui_text(prop, "Asymmetry", "Continuum between forward scattering and back scattering"); + RNA_def_property_ui_text(prop, "Asymmetry", "Back scattering (-1.0) to Forward scattering (1.0) and the range in between."); RNA_def_property_update(prop, 0, "rna_Material_update"); } diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index d63f5823b2e..7bc8570ce13 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -955,11 +955,11 @@ static void rna_def_texture_image(BlenderRNA *brna) PropertyRNA *prop; static EnumPropertyItem prop_image_extension[] = { - {1, "EXTEND", 0, "Extend", "Extends by repeating edge pixels of the image"}, - {2, "CLIP", 0, "Clip", "Clips to image size and sets exterior pixels as transparent"}, - {4, "CLIP_CUBE", 0, "Clip Cube", "Clips to cubic-shaped area around the image and sets exterior pixels as transparent"}, - {3, "REPEAT", 0, "Repeat", "Causes the image to repeat horizontally and vertically"}, - {5, "CHECKER", 0, "Checker", "Causes the image to repeat in checker board pattern"}, + {TEX_EXTEND, "EXTEND", 0, "Extend", "Extends by repeating edge pixels of the image"}, + {TEX_CLIP, "CLIP", 0, "Clip", "Clips to image size and sets exterior pixels as transparent"}, + {TEX_CLIPCUBE, "CLIP_CUBE", 0, "Clip Cube", "Clips to cubic-shaped area around the image and sets exterior pixels as transparent"}, + {TEX_REPEAT, "REPEAT", 0, "Repeat", "Causes the image to repeat horizontally and vertically"}, + {TEX_CHECKER, "CHECKER", 0, "Checker", "Causes the image to repeat in checker board pattern"}, {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "ImageTexture", "Texture"); @@ -1016,7 +1016,7 @@ static void rna_def_texture_image(BlenderRNA *brna) prop= RNA_def_property(srna, "extension", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "extend"); RNA_def_property_enum_items(prop, prop_image_extension); - RNA_def_property_ui_text(prop, "Extension", "Sets how the image is stretched in the texture"); + RNA_def_property_ui_text(prop, "Extension", "Sets how the image is extrapolated past its original bounds"); RNA_def_property_update(prop, 0, "rna_Texture_update"); prop= RNA_def_property(srna, "repeat_x", PROP_INT, PROP_NONE); @@ -1562,6 +1562,12 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna) {TEX_VD_IMAGE_SEQUENCE, "IMAGE_SEQUENCE", 0, "Image Sequence", "Generate voxels from a sequence of image slices"}, {TEX_VD_SMOKE, "SMOKE", 0, "Smoke", "Render voxels from a Blender smoke simulation"}, {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem voxeldata_extension[] = { + {TEX_EXTEND, "EXTEND", 0, "Extend", "Extends by repeating edge pixels of the image"}, + {TEX_CLIP, "CLIP", 0, "Clip", "Clips to image size and sets exterior pixels as transparent"}, + {TEX_REPEAT, "REPEAT", 0, "Repeat", "Causes the image to repeat horizontally and vertically"}, + {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "VoxelData", NULL); RNA_def_struct_sdna(srna, "VoxelData"); @@ -1573,6 +1579,12 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Interpolation", "Method to interpolate/smooth values between voxel cells"); RNA_def_property_update(prop, 0, "rna_Texture_update"); + prop= RNA_def_property(srna, "extension", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "extend"); + RNA_def_property_enum_items(prop, voxeldata_extension); + RNA_def_property_ui_text(prop, "Extension", "Sets how the texture is extrapolated past its original bounds"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + prop= RNA_def_property(srna, "intensity", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "int_multiplier"); RNA_def_property_range(prop, 0.01, FLT_MAX); 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 48a7c003c9f..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; } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index c1d0c943ca9..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) { diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 4830dab7d37..02b7f6aad86 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -2385,7 +2385,7 @@ 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))) { + 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], colfac; /* stencil maps on the texture control slider, not texture intensity value */ @@ -2413,8 +2413,11 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype); } - /* MAP_COLMIR is abused for absorption colour at the moment */ - if((mapto_flag & MAP_ABSORPTION_COL) && (mtex->mapto & MAP_ABSORPTION_COL)) { + if((mapto_flag & MAP_REFLECTION_COL) && (mtex->mapto & MAP_REFLECTION_COL)) { + texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype); + } + + if((mapto_flag & MAP_TRANSMISSION_COL) && (mtex->mapto & MAP_TRANSMISSION_COL)) { texture_rgb_blend(col, tcol, col, texres.tin, colfac, mtex->blendtype); } } @@ -2443,14 +2446,14 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip); 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)) { + int flip= mtex->maptoneg & MAP_SCATTERING; *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip); 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)) { + int flip= mtex->maptoneg & MAP_REFLECTION; *val = texture_value_blend(mtex->def_var, *val, texres.tin, varfac, mtex->blendtype, flip); CLAMP(*val, 0.0, 1.0); 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 b2692c25b99..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,8 +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 p, ref_col[3]; if (lar->mode & LA_LAYER) if((lar->lay & shi->obi->lay)==0) return; if ((lar->lay & shi->lay)==0) return; @@ -475,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; @@ -515,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 */ @@ -606,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. @@ -709,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); } diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c index 9318d37620c..479f33c9ff2 100644 --- a/source/blender/render/intern/source/voxeldata.c +++ b/source/blender/render/intern/source/voxeldata.c @@ -226,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); @@ -259,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); |