diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2010-01-28 00:40:08 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2010-01-28 00:40:08 +0300 |
commit | 5445dda2956d64385b20874592b3305b7056505a (patch) | |
tree | 59975e804583931180994c24b0d3d04e485e7d0f /source | |
parent | 478dc000b3d65af48422154769641a3ecbe071d8 (diff) |
Ambient Occlusion split up into:
Ambient occlusion: multiplied with direct lighting by default, add
is also still available and more blending methods might be added if
they are useful. This is fundamentally a non physical effect.
Environment lighting: always added as you would expect (though you can
subtract by specifying negative energy). This can be just white or take
colors or textures from the world.
Indirect lighting: only supported for AAO at the moment (and is still
too approximate), and also is always added. A factor is available to
specify how much is added, though value 1.0 is correct.
Also:
* Material ambient value now defaults to 1.0.
* Added Environment, Indirect and Emit pass.
* "Both" blending method is no longer available.
* Attenuation, sampling parameters are still shared, some could be split
up, though if they are different this would affect performance.
Diffstat (limited to 'source')
21 files changed, 468 insertions, 228 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 37b98565ea3..45df0913079 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -43,7 +43,7 @@ struct bContext; struct ReportList; #define BLENDER_VERSION 250 -#define BLENDER_SUBVERSION 14 +#define BLENDER_SUBVERSION 15 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 3567c061f04..2d4ff857b2a 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -112,7 +112,7 @@ void init_material(Material *ma) ma->specr= ma->specg= ma->specb= 1.0; ma->mirr= ma->mirg= ma->mirb= 1.0; ma->spectra= 1.0; - ma->amb= 0.5; + ma->amb= 1.0; ma->alpha= 1.0; ma->spec= ma->hasize= 0.5; ma->har= 50; diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index b5f8bc81b81..0b49808bf15 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -102,6 +102,9 @@ World *add_world(char *name) wrld->aodist= 10.0f; wrld->aosamp= 5; wrld->aoenergy= 1.0f; + wrld->ao_env_energy= 1.0f; + wrld->ao_indirect_energy= 1.0f; + wrld->ao_indirect_bounces= 1; wrld->aobias= 0.05f; wrld->ao_samp_method = WO_AOSAMP_HAMMERSLEY; wrld->ao_approx_error= 0.25f; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index c3457adc288..84b27ad44eb 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -10604,6 +10604,36 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 15)) { + World *wo; + Material *ma; + + /* ambient default from 0.5f to 1.0f */ + for(ma= main->mat.first; ma; ma=ma->id.next) + ma->amb *= 2.0f; + + for(wo= main->world.first; wo; wo=wo->id.next) { + /* ao splitting into ao/env/indirect */ + wo->ao_env_energy= wo->aoenergy; + wo->aoenergy= 1.0f; + + if(wo->ao_indirect_bounces == 0) + wo->ao_indirect_bounces= 1; + else + wo->mode |= WO_INDIRECT_LIGHT; + + if(wo->aomix == WO_AOSUB) + wo->ao_env_energy= -wo->ao_env_energy; + else if(wo->aomix == WO_AOADDSUB) + wo->mode |= WO_AMB_OCC; + + wo->aomix= WO_AOMUL; + + /* ambient default from 0.5f to 1.0f */ + mul_v3_fl(&wo->ambr, 0.5f); + wo->ao_env_energy *= 0.5f; + } + } /* put 2.50 compatibility code here until next subversion bump */ //{ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 4caae9e1dfc..636596f7af7 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -170,23 +170,25 @@ typedef struct SceneRenderLayer { #define SCE_LAY_NEG_ZMASK 0x80000 /* srl->passflag */ -#define SCE_PASS_COMBINED 1 -#define SCE_PASS_Z 2 -#define SCE_PASS_RGBA 4 -#define SCE_PASS_DIFFUSE 8 -#define SCE_PASS_SPEC 16 -#define SCE_PASS_SHADOW 32 -#define SCE_PASS_AO 64 -#define SCE_PASS_REFLECT 128 -#define SCE_PASS_NORMAL 256 -#define SCE_PASS_VECTOR 512 -#define SCE_PASS_REFRACT 1024 -#define SCE_PASS_INDEXOB 2048 -#define SCE_PASS_UV 4096 -#define SCE_PASS_RADIO 8192 /* Radio removed, can use for new GI? */ -#define SCE_PASS_MIST 16384 - -#define SCE_PASS_RAYHITS 32768 +#define SCE_PASS_COMBINED 1 +#define SCE_PASS_Z 2 +#define SCE_PASS_RGBA 4 +#define SCE_PASS_DIFFUSE 8 +#define SCE_PASS_SPEC 16 +#define SCE_PASS_SHADOW 32 +#define SCE_PASS_AO 64 +#define SCE_PASS_REFLECT 128 +#define SCE_PASS_NORMAL 256 +#define SCE_PASS_VECTOR 512 +#define SCE_PASS_REFRACT 1024 +#define SCE_PASS_INDEXOB 2048 +#define SCE_PASS_UV 4096 +#define SCE_PASS_RADIO 8192 /* Radio removed, can use for new GI? */ +#define SCE_PASS_MIST 16384 +#define SCE_PASS_RAYHITS 32768 +#define SCE_PASS_EMIT 65536 +#define SCE_PASS_ENVIRONMENT 131072 +#define SCE_PASS_INDIRECT 262144 /* note, srl->passflag is treestore element 'nr' in outliner, short still... */ diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index 9b3f78caee0..b79bc766d17 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -107,7 +107,7 @@ typedef struct World { short aomode, aosamp, aomix, aocolor; float ao_adapt_thresh, ao_adapt_speed_fac; float ao_approx_error, ao_approx_correction; - float ao_indirect_energy; + float ao_indirect_energy, ao_env_energy, ao_pad2; short ao_indirect_bounces, ao_pad; short ao_samp_method, ao_gather_method, ao_approx_passes; @@ -142,13 +142,16 @@ typedef struct World { #define WO_STARS 2 #define WO_DOF 4 #define WO_ACTIVITY_CULLING 8 -#define WO_AMB_OCC 16 +#define WO_ENV_LIGHT 16 #define WO_DBVT_CULLING 32 +#define WO_AMB_OCC 64 +#define WO_INDIRECT_LIGHT 128 /* aomix */ #define WO_AOADD 0 -#define WO_AOSUB 1 -#define WO_AOADDSUB 2 +#define WO_AOSUB 1 /* deprecated */ +#define WO_AOADDSUB 2 /* deprecated */ +#define WO_AOMUL 3 /* ao_samp_method - methods for sampling the AO hemi */ #define WO_AOSAMP_CONSTANT 0 diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 8212423acd5..85fd33f6c63 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -369,6 +369,8 @@ static void rna_def_render_pass(BlenderRNA *brna) {SCE_PASS_INDEXOB, "OBJECT_INDEX", 0, "Object Index", ""}, {SCE_PASS_UV, "UV", 0, "UV", ""}, {SCE_PASS_MIST, "MIST", 0, "Mist", ""}, + {SCE_PASS_EMIT, "EMIT", 0, "Emit", ""}, + {SCE_PASS_ENVIRONMENT, "ENVIRONMENT", 0, "Environment", ""}, {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "RenderPass", NULL); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 7e4fc9aa9e0..3f79a06566d 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1142,6 +1142,24 @@ void rna_def_render_layer_common(StructRNA *srna, int scene) if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update"); else RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop= RNA_def_property(srna, "pass_emit", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_EMIT); + RNA_def_property_ui_text(prop, "Emit", "Deliver emission pass."); + if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update"); + else RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop= RNA_def_property(srna, "pass_environment", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_ENVIRONMENT); + RNA_def_property_ui_text(prop, "Environment", "Deliver environment lighting pass."); + if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update"); + else RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop= RNA_def_property(srna, "pass_indirect", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_INDIRECT); + RNA_def_property_ui_text(prop, "Indirect", "Deliver indirect lighting pass."); + if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update"); + else RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop= RNA_def_property(srna, "pass_specular_exclude", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "pass_xor", SCE_PASS_SPEC); RNA_def_property_ui_text(prop, "Specular Exclude", "Exclude specular pass from combined."); @@ -1171,6 +1189,24 @@ void rna_def_render_layer_common(StructRNA *srna, int scene) RNA_def_property_ui_text(prop, "Refraction Exclude", "Exclude raytraced refraction pass from combined."); if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update"); else RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop= RNA_def_property(srna, "pass_emit_exclude", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pass_xor", SCE_PASS_EMIT); + RNA_def_property_ui_text(prop, "Emit Exclude", "Exclude emission pass from combined."); + if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update"); + else RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop= RNA_def_property(srna, "pass_environment_exclude", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pass_xor", SCE_PASS_ENVIRONMENT); + RNA_def_property_ui_text(prop, "Environment Exclude", "Exclude environment pass from combined."); + if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update"); + else RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop= RNA_def_property(srna, "pass_indirect_exclude", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pass_xor", SCE_PASS_INDIRECT); + RNA_def_property_ui_text(prop, "Indirect Exclude", "Exclude indirect pass from combined."); + if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_SceneRenderLayer_pass_update"); + else RNA_def_property_clear_flag(prop, PROP_EDITABLE); } static void rna_def_scene_game_data(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index 4046fc266da..c2af18193b2 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -45,9 +45,9 @@ #include "WM_api.h" #include "WM_types.h" -static PointerRNA rna_World_ambient_occlusion_get(PointerRNA *ptr) +static PointerRNA rna_World_lighting_get(PointerRNA *ptr) { - return rna_pointer_inherit_refine(ptr, &RNA_WorldAmbientOcclusion, ptr->id.data); + return rna_pointer_inherit_refine(ptr, &RNA_WorldLighting, ptr->id.data); } static PointerRNA rna_World_stars_get(PointerRNA *ptr) @@ -182,15 +182,14 @@ static void rna_def_world_mtex(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_World_update"); } -static void rna_def_ambient_occlusion(BlenderRNA *brna) +static void rna_def_lighting(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; static EnumPropertyItem blend_mode_items[] = { + {WO_AOMUL, "MULTIPLY", 0, "Multiply", "Multiply direct lighting with ambient occlusion, darkening the result."}, {WO_AOADD, "ADD", 0, "Add", "Add light and shadow."}, - {WO_AOSUB, "SUBTRACT", 0, "Subtract", "Subtract light and shadow (needs a normal light to make anything visible.)"}, - {WO_AOADDSUB, "BOTH", 0, "Both", "Both lighten and darken."}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem prop_color_items[] = { @@ -210,14 +209,78 @@ static void rna_def_ambient_occlusion(BlenderRNA *brna) {WO_AOGATHER_APPROX, "APPROXIMATE", 0, "Approximate", "Inaccurate, but faster and without noise."}, {0, NULL, 0, NULL, NULL}}; - srna= RNA_def_struct(brna, "WorldAmbientOcclusion", NULL); + srna= RNA_def_struct(brna, "WorldLighting", NULL); RNA_def_struct_sdna(srna, "World"); RNA_def_struct_nested(brna, srna, "World"); - RNA_def_struct_ui_text(srna, "Ambient Occlusion", "Ambient occlusion settings for a World datablock."); + RNA_def_struct_ui_text(srna, "Lighting", "Lighting for a World datablock."); - prop= RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE); + /* ambient occlusion */ + prop= RNA_def_property(srna, "use_ambient_occlusion", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", WO_AMB_OCC); - RNA_def_property_ui_text(prop, "Enabled", "Use Ambient Occlusion to add light based on distance between elements, creating the illusion of omnipresent light"); + RNA_def_property_ui_text(prop, "Use Ambient Occlusion", "Use Ambient Occlusion to add shadowing based on distance between objects."); + RNA_def_property_update(prop, 0, "rna_World_update"); + + prop= RNA_def_property(srna, "ao_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "aoenergy"); + RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 0.1, 2); + RNA_def_property_ui_text(prop, "Factor", "Factor for ambient occlusion blending blending."); + RNA_def_property_update(prop, 0, "rna_World_update"); + + prop= RNA_def_property(srna, "ao_blend_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "aomix"); + RNA_def_property_enum_items(prop, blend_mode_items); + RNA_def_property_ui_text(prop, "Blend Mode", "Defines how AO mixes with material shading."); + RNA_def_property_update(prop, 0, "rna_World_update"); + + /* environment lighting */ + prop= RNA_def_property(srna, "use_environment_lighting", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mode", WO_ENV_LIGHT); + RNA_def_property_ui_text(prop, "Use Environment Lighting", "Add light coming from the environment."); + RNA_def_property_update(prop, 0, "rna_World_update"); + + prop= RNA_def_property(srna, "environment_energy", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "ao_env_energy"); + RNA_def_property_ui_range(prop, 0, FLT_MAX, 0.1, 2); + RNA_def_property_ui_text(prop, "Environment Color", "Defines the strength of environment light."); + RNA_def_property_update(prop, 0, "rna_World_update"); + + prop= RNA_def_property(srna, "environment_color", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "aocolor"); + RNA_def_property_enum_items(prop, prop_color_items); + RNA_def_property_ui_text(prop, "Environment Color", "Defines where the color of the environment light comes from."); + RNA_def_property_update(prop, 0, "rna_World_update"); + + /* indirect lighting */ + prop= RNA_def_property(srna, "use_indirect_lighting", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mode", WO_INDIRECT_LIGHT); + RNA_def_property_ui_text(prop, "Use Indirect Lighting", "Add indirect light bouncing of surrounding objects."); + RNA_def_property_update(prop, 0, "rna_World_update"); + + prop= RNA_def_property(srna, "indirect_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "ao_indirect_energy"); + RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_ui_range(prop, 0, 1, 0.1, 2); + RNA_def_property_ui_text(prop, "Indirect Factor", "Factor for how much surrounding objects contribute to light."); + RNA_def_property_update(prop, 0, "rna_World_update"); + + prop= RNA_def_property(srna, "indirect_bounces", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "ao_indirect_bounces"); + RNA_def_property_range(prop, 1, INT_MAX); + RNA_def_property_ui_text(prop, "Bounces", "Number of indirect diffuse light bounces to use for approximate ambient occlusion."); + RNA_def_property_update(prop, 0, "rna_World_update"); + + /* gathering parameters */ + prop= RNA_def_property(srna, "gather_method", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "ao_gather_method"); + RNA_def_property_enum_items(prop, prop_gather_method_items); + RNA_def_property_ui_text(prop, "Gather Method", ""); + RNA_def_property_update(prop, 0, "rna_World_update"); + + prop= RNA_def_property(srna, "passes", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "ao_approx_passes"); + RNA_def_property_range(prop, 0, 10); + RNA_def_property_ui_text(prop, "Passes", "Number of preprocessing passes to reduce overocclusion (for Approximate)."); RNA_def_property_update(prop, 0, "rna_World_update"); prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE); @@ -230,12 +293,6 @@ static void rna_def_ambient_occlusion(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Strength", "Distance attenuation factor, the higher, the 'shorter' the shadows."); RNA_def_property_update(prop, 0, "rna_World_update"); - prop= RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "aoenergy"); - RNA_def_property_ui_range(prop, 0, 10, 0.1, 3); - RNA_def_property_ui_text(prop, "Energy", "Amount of enerygy generated by ambient occlusion."); - RNA_def_property_update(prop, 0, "rna_World_update"); - prop= RNA_def_property(srna, "bias", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "aobias"); RNA_def_property_range(prop, 0, 0.5); @@ -283,46 +340,11 @@ static void rna_def_ambient_occlusion(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Samples", "Amount of ray samples. Higher values give smoother results and longer rendering times"); RNA_def_property_update(prop, 0, "rna_World_update"); - prop= RNA_def_property(srna, "blend_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "aomix"); - RNA_def_property_enum_items(prop, blend_mode_items); - RNA_def_property_ui_text(prop, "Blend Mode", "Defines how AO mixes with material shading."); - RNA_def_property_update(prop, 0, "rna_World_update"); - - prop= RNA_def_property(srna, "color", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "aocolor"); - RNA_def_property_enum_items(prop, prop_color_items); - RNA_def_property_ui_text(prop, "Color", "Defines the color of the AO light"); - RNA_def_property_update(prop, 0, "rna_World_update"); - prop= RNA_def_property(srna, "sample_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "ao_samp_method"); RNA_def_property_enum_items(prop, prop_sample_method_items); RNA_def_property_ui_text(prop, "Sample Method", "Method for generating shadow samples (for Raytrace)."); RNA_def_property_update(prop, 0, "rna_World_update"); - - prop= RNA_def_property(srna, "gather_method", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "ao_gather_method"); - RNA_def_property_enum_items(prop, prop_gather_method_items); - RNA_def_property_ui_text(prop, "Gather Method", ""); - RNA_def_property_update(prop, 0, "rna_World_update"); - - prop= RNA_def_property(srna, "passes", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "ao_approx_passes"); - RNA_def_property_range(prop, 0, 10); - RNA_def_property_ui_text(prop, "Passes", "Number of preprocessing passes to reduce overocclusion (for Approximate)."); - RNA_def_property_update(prop, 0, "rna_World_update"); - - prop= RNA_def_property(srna, "indirect_energy", PROP_FLOAT, PROP_UNSIGNED); - RNA_def_property_float_sdna(prop, NULL, "ao_indirect_energy"); - RNA_def_property_ui_range(prop, 0, 10, 0.1, 3); - RNA_def_property_ui_text(prop, "Indirect", "Use approximate ambient occlusion for indirect diffuse lighting."); - RNA_def_property_update(prop, 0, "rna_World_update"); - - prop= RNA_def_property(srna, "indirect_bounces", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "ao_indirect_bounces"); - RNA_def_property_ui_text(prop, "Bounces", "Number of indirect diffuse light bounces to use for approximate ambient occlusion."); - RNA_def_property_update(prop, 0, "rna_World_update"); } static void rna_def_world_mist(BlenderRNA *brna) @@ -499,11 +521,11 @@ void RNA_def_world(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_World_update"); /* nested structs */ - prop= RNA_def_property(srna, "ambient_occlusion", PROP_POINTER, PROP_NONE); + prop= RNA_def_property(srna, "lighting", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); - RNA_def_property_struct_type(prop, "WorldAmbientOcclusion"); - RNA_def_property_pointer_funcs(prop, "rna_World_ambient_occlusion_get", NULL, NULL); - RNA_def_property_ui_text(prop, "Ambient Occlusion", "World ambient occlusion settings."); + RNA_def_property_struct_type(prop, "WorldLighting"); + RNA_def_property_pointer_funcs(prop, "rna_World_lighting_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Lighting", "World lighting settings."); prop= RNA_def_property(srna, "mist", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); @@ -517,7 +539,7 @@ void RNA_def_world(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, "rna_World_stars_get", NULL, NULL); RNA_def_property_ui_text(prop, "Stars", "World stars settings."); - rna_def_ambient_occlusion(brna); + rna_def_lighting(brna); rna_def_world_mist(brna); rna_def_world_stars(brna); rna_def_world_mtex(brna); diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 28d88e1f8b4..a7c0f9511a5 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -49,10 +49,13 @@ typedef struct ShadeResult float combined[4]; float col[4]; float alpha, mist, z; + float emit[3]; float diff[3]; /* no ramps, shadow, etc */ float spec[3]; float shad[3]; float ao[3]; + float env[3]; + float indirect[3]; float refl[3]; float refr[3]; float nor[3]; @@ -153,7 +156,7 @@ typedef struct ShadeInput float dxstrand, dystrand; /* AO is a pre-process now */ - float ao[3], indirect[3]; + float ao[3], indirect[3], env[3]; int xs, ys; /* pixel to be rendered */ int mask; /* subsample mask */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index d41851db5ff..ba995621a98 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -399,6 +399,7 @@ typedef struct StrandSurface { float (*co)[3]; /* for occlusion caching */ float (*ao)[3]; + float (*env)[3]; float (*indirect)[3]; /* for speedvectors */ float (*prevco)[3], (*nextco)[3]; diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 250fbc000cb..e97ab1de9bb 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -99,7 +99,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi); extern void ray_shadow(ShadeInput *, LampRen *, float *); extern void ray_trace(ShadeInput *, ShadeResult *); -extern void ray_ao(ShadeInput *, float *); +extern void ray_ao(ShadeInput *, float *, float *); extern void init_jitter_plane(LampRen *lar); extern void init_ao_sphere(struct World *wrld); extern void init_render_qmcsampler(Render *re); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 63782223c33..a8afc40f04d 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1701,7 +1701,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem if(re->r.mode & R_SPEED) dosurfacecache= 1; - else if((re->wrld.mode & WO_AMB_OCC) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX)) + else if((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX)) if(ma->amb != 0.0f) dosurfacecache= 1; @@ -3811,7 +3811,7 @@ void init_render_world(Render *re) while(re->wrld.aosamp*re->wrld.aosamp < re->osa) re->wrld.aosamp++; if(!(re->r.mode & R_RAYTRACE) && (re->wrld.ao_gather_method == WO_AOGATHER_RAYTRACE)) - re->wrld.mode &= ~WO_AMB_OCC; + re->wrld.mode &= ~(WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT); } else { memset(&re->wrld, 0, sizeof(World)); @@ -4849,7 +4849,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) if(re->r.mode & R_RAYTRACE) { init_render_qmcsampler(re); - if(re->wrld.mode & WO_AMB_OCC) + if(re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) init_ao_sphere(&re->wrld); } @@ -4925,7 +4925,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) project_renderdata(re, projectverto, re->r.mode & R_PANORAMA, 0, 1); /* Occlusion */ - if((re->wrld.mode & WO_AMB_OCC) && !re->test_break(re->tbh)) + if((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && !re->test_break(re->tbh)) if(re->wrld.ao_gather_method == WO_AOGATHER_APPROX) if(re->r.renderer==R_INTERN) if(re->r.mode & R_SHADOW) @@ -5537,7 +5537,7 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob) if(re->r.mode & R_RAYTRACE) { init_render_qmcsampler(re); - if(re->wrld.mode & WO_AMB_OCC) + if(re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) init_ao_sphere(&re->wrld); } @@ -5569,7 +5569,7 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob) makeraytree(re); /* occlusion */ - if((re->wrld.mode & WO_AMB_OCC) && !re->test_break(re->tbh)) + if((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && !re->test_break(re->tbh)) if(re->wrld.ao_gather_method == WO_AOGATHER_APPROX) if(re->r.mode & R_SHADOW) make_occ_tree(re); diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c index 40fcc2b399a..d06339f75cc 100644 --- a/source/blender/render/intern/source/occlusion.c +++ b/source/blender/render/intern/source/occlusion.c @@ -64,7 +64,7 @@ #define CACHE_STEP 3 typedef struct OcclusionCacheSample { - float co[3], n[3], ao[3], indirect[3], intensity, dist2; + float co[3], n[3], ao[3], env[3], indirect[3], intensity, dist2; int x, y, filled; } OcclusionCacheSample; @@ -120,6 +120,7 @@ typedef struct OcclusionThread { Render *re; StrandSurface *mesh; float (*faceao)[3]; + float (*faceenv)[3]; float (*faceindirect)[3]; int begin, end; int thread; @@ -1375,19 +1376,19 @@ static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass) MEM_freeN(occ); } -static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, float *co, float *n, int thread, int onlyshadow, float *ao, float *indirect) +static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, float *co, float *n, int thread, int onlyshadow, float *ao, float *env, float *indirect) { float nn[3], bn[3], fac, occ, occlusion, correction, rad[3]; - int aocolor; + int envcolor; - aocolor= re->wrld.aocolor; + envcolor= re->wrld.aocolor; if(onlyshadow) - aocolor= WO_AOPLAIN; + envcolor= WO_AOPLAIN; VECCOPY(nn, n); negate_v3(nn); - occ_lookup(tree, thread, exclude, co, nn, &occ, (tree->doindirect)? rad: NULL, (aocolor)? bn: NULL); + occ_lookup(tree, thread, exclude, co, nn, &occ, (tree->doindirect)? rad: NULL, (env && envcolor)? bn: NULL); correction= re->wrld.ao_approx_correction; @@ -1396,13 +1397,20 @@ static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, f if(correction != 0.0f) occlusion += correction*exp(-occ); - if(aocolor) { + if(env) { /* sky shading using bent normal */ - if(ELEM(aocolor, WO_AOSKYCOL, WO_AOSKYTEX)) { + if(ELEM(envcolor, WO_AOSKYCOL, WO_AOSKYTEX)) { fac= 0.5*(1.0f+bn[0]*re->grvec[0]+ bn[1]*re->grvec[1]+ bn[2]*re->grvec[2]); - ao[0]= (1.0f-fac)*re->wrld.horr + fac*re->wrld.zenr; - ao[1]= (1.0f-fac)*re->wrld.horg + fac*re->wrld.zeng; - ao[2]= (1.0f-fac)*re->wrld.horb + fac*re->wrld.zenb; + env[0]= (1.0f-fac)*re->wrld.horr + fac*re->wrld.zenr; + env[1]= (1.0f-fac)*re->wrld.horg + fac*re->wrld.zeng; + env[2]= (1.0f-fac)*re->wrld.horb + fac*re->wrld.zenb; + + mul_v3_fl(env, occlusion); + } + else { + env[0]= occlusion; + env[1]= occlusion; + env[2]= occlusion; } #if 0 else { /* WO_AOSKYTEX */ @@ -1416,10 +1424,9 @@ static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, f shadeSkyView(ao, co, bn, dxyview); } #endif - - mul_v3_fl(ao, occlusion); } - else { + + if(ao) { ao[0]= occlusion; ao[1]= occlusion; ao[2]= occlusion; @@ -1447,7 +1454,7 @@ static OcclusionCacheSample *find_occ_sample(OcclusionCache *cache, int x, int y return &cache->sample[y*cache->w + x]; } -static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int y, int thread, float *ao, float *indirect) +static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int y, int thread, float *ao, float *env, float *indirect) { OcclusionCache *cache; OcclusionCacheSample *samples[4], *sample; @@ -1468,6 +1475,7 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int dist2= INPR(d, d); if(dist2 < 0.5f*sample->dist2 && INPR(sample->n, n) > 0.98f) { VECCOPY(ao, sample->ao); + VECCOPY(env, sample->env); VECCOPY(indirect, sample->indirect); return 1; } @@ -1495,6 +1503,7 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int /* compute weighted interpolation between samples */ zero_v3(ao); + zero_v3(env); zero_v3(indirect); totw= 0.0f; @@ -1522,12 +1531,14 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int totw += w; madd_v3_v3fl(ao, samples[i]->ao, w); + madd_v3_v3fl(env, samples[i]->env, w); madd_v3_v3fl(indirect, samples[i]->indirect, w); } if(totw >= 0.9f) { totw= 1.0f/totw; mul_v3_fl(ao, totw); + mul_v3_fl(env, totw); mul_v3_fl(indirect, totw); return 1; } @@ -1553,16 +1564,21 @@ static void sample_occ_surface(ShadeInput *shi) interp_weights_face_v3(w, co1, co2, co3, co4, strand->vert->co); zero_v3(shi->ao); + zero_v3(shi->env); zero_v3(shi->indirect); madd_v3_v3fl(shi->ao, mesh->ao[face[0]], w[0]); + madd_v3_v3fl(shi->env, mesh->env[face[0]], w[0]); madd_v3_v3fl(shi->indirect, mesh->indirect[face[0]], w[0]); madd_v3_v3fl(shi->ao, mesh->ao[face[1]], w[1]); + madd_v3_v3fl(shi->env, mesh->env[face[1]], w[1]); madd_v3_v3fl(shi->indirect, mesh->indirect[face[1]], w[1]); madd_v3_v3fl(shi->ao, mesh->ao[face[2]], w[2]); + madd_v3_v3fl(shi->env, mesh->env[face[2]], w[2]); madd_v3_v3fl(shi->indirect, mesh->indirect[face[2]], w[2]); if(face[3]) { madd_v3_v3fl(shi->ao, mesh->ao[face[3]], w[3]); + madd_v3_v3fl(shi->env, mesh->env[face[3]], w[3]); madd_v3_v3fl(shi->indirect, mesh->indirect[face[3]], w[3]); } } @@ -1570,6 +1586,7 @@ static void sample_occ_surface(ShadeInput *shi) shi->ao[0]= 1.0f; shi->ao[1]= 1.0f; shi->ao[2]= 1.0f; + zero_v3(shi->env); zero_v3(shi->indirect); } } @@ -1581,7 +1598,7 @@ static void *exec_strandsurface_sample(void *data) OcclusionThread *othread= (OcclusionThread*)data; Render *re= othread->re; StrandSurface *mesh= othread->mesh; - float ao[3], indirect[3], co[3], n[3], *co1, *co2, *co3, *co4; + float ao[3], env[3], indirect[3], co[3], n[3], *co1, *co2, *co3, *co4; int a, *face; for(a=othread->begin; a<othread->end; a++) { @@ -1602,8 +1619,9 @@ static void *exec_strandsurface_sample(void *data) } negate_v3(n); - sample_occ_tree(re, re->occlusiontree, NULL, co, n, othread->thread, 0, ao, indirect); + sample_occ_tree(re, re->occlusiontree, NULL, co, n, othread->thread, 0, ao, env, indirect); VECCOPY(othread->faceao[a], ao); + VECCOPY(othread->faceenv[a], env); VECCOPY(othread->faceindirect[a], indirect); } @@ -1616,7 +1634,7 @@ void make_occ_tree(Render *re) OcclusionTree *tree; StrandSurface *mesh; ListBase threads; - float ao[3], indirect[3], (*faceao)[3], (*faceindirect)[3]; + float ao[3], env[3], indirect[3], (*faceao)[3], (*faceenv)[3], (*faceindirect)[3]; int a, totface, totthread, *face, *count; /* ugly, needed for occ_face */ @@ -1630,7 +1648,7 @@ void make_occ_tree(Render *re) if(tree) { if(re->wrld.ao_approx_passes > 0) occ_compute_passes(re, tree, re->wrld.ao_approx_passes); - if(tree->doindirect && re->wrld.ao_indirect_bounces > 1) + if(tree->doindirect && (re->wrld.mode & WO_INDIRECT_LIGHT)) occ_compute_bounces(re, tree, re->wrld.ao_indirect_bounces); for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) { @@ -1639,6 +1657,7 @@ void make_occ_tree(Render *re) count= MEM_callocN(sizeof(int)*mesh->totvert, "OcclusionCount"); faceao= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceAO"); + faceenv= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceEnv"); faceindirect= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceIndirect"); totthread= (mesh->totface > 10000)? re->r.threads: 1; @@ -1646,6 +1665,7 @@ void make_occ_tree(Render *re) for(a=0; a<totthread; a++) { othreads[a].re= re; othreads[a].faceao= faceao; + othreads[a].faceenv= faceenv; othreads[a].faceindirect= faceindirect; othreads[a].thread= a; othreads[a].mesh= mesh; @@ -1669,20 +1689,25 @@ void make_occ_tree(Render *re) face= mesh->face[a]; VECCOPY(ao, faceao[a]); + VECCOPY(env, faceenv[a]); VECCOPY(indirect, faceindirect[a]); VECADD(mesh->ao[face[0]], mesh->ao[face[0]], ao); + VECADD(mesh->env[face[0]], mesh->env[face[0]], env); VECADD(mesh->indirect[face[0]], mesh->indirect[face[0]], indirect); count[face[0]]++; VECADD(mesh->ao[face[1]], mesh->ao[face[1]], ao); + VECADD(mesh->env[face[1]], mesh->env[face[1]], env); VECADD(mesh->indirect[face[1]], mesh->indirect[face[1]], indirect); count[face[1]]++; VECADD(mesh->ao[face[2]], mesh->ao[face[2]], ao); + VECADD(mesh->env[face[2]], mesh->env[face[2]], env); VECADD(mesh->indirect[face[2]], mesh->indirect[face[2]], indirect); count[face[2]]++; if(face[3]) { VECADD(mesh->ao[face[3]], mesh->ao[face[3]], ao); + VECADD(mesh->env[face[3]], mesh->env[face[3]], env); VECADD(mesh->indirect[face[3]], mesh->indirect[face[3]], indirect); count[face[3]]++; } @@ -1691,12 +1716,14 @@ void make_occ_tree(Render *re) for(a=0; a<mesh->totvert; a++) { if(count[a]) { mul_v3_fl(mesh->ao[a], 1.0f/count[a]); + mul_v3_fl(mesh->env[a], 1.0f/count[a]); mul_v3_fl(mesh->indirect[a], 1.0f/count[a]); } } MEM_freeN(count); MEM_freeN(faceao); + MEM_freeN(faceenv); MEM_freeN(faceindirect); } } @@ -1723,12 +1750,12 @@ void sample_occ(Render *re, ShadeInput *shi) sample_occ_surface(shi); } /* try to get result from the cache if possible */ - else if(shi->depth!=0 || !sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao, shi->indirect)) { + else if(shi->depth!=0 || !sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao, shi->env, shi->indirect)) { /* no luck, let's sample the occlusion */ exclude.obi= shi->obi - re->objectinstance; exclude.facenr= shi->vlr->index; onlyshadow= (shi->mat->mode & MA_ONLYSHADOW); - sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao, shi->indirect); + sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao, shi->env, shi->indirect); /* fill result into sample, each time */ if(tree->cache) { @@ -1739,8 +1766,10 @@ void sample_occ(Render *re, ShadeInput *shi) VECCOPY(sample->co, shi->co); VECCOPY(sample->n, shi->vno); VECCOPY(sample->ao, shi->ao); + VECCOPY(sample->env, shi->env); VECCOPY(sample->indirect, shi->indirect); sample->intensity= MAX3(sample->ao[0], sample->ao[1], sample->ao[2]); + sample->intensity= MAX2(sample->intensity, MAX3(sample->env[0], sample->env[1], sample->env[2])); sample->intensity= MAX2(sample->intensity, MAX3(sample->indirect[0], sample->indirect[1], sample->indirect[2])); sample->dist2= INPR(shi->dxco, shi->dxco) + INPR(shi->dyco, shi->dyco); sample->filled= 1; @@ -1753,6 +1782,10 @@ void sample_occ(Render *re, ShadeInput *shi) shi->ao[1]= 1.0f; shi->ao[2]= 1.0f; + shi->env[0]= 0.0f; + shi->env[1]= 0.0f; + shi->env[2]= 0.0f; + shi->indirect[0]= 0.0f; shi->indirect[1]= 0.0f; shi->indirect[2]= 0.0f; @@ -1823,13 +1856,15 @@ void cache_occ_samples(Render *re, RenderPart *pa, ShadeSample *ssamp) onlyshadow= (shi->mat->mode & MA_ONLYSHADOW); exclude.obi= shi->obi - re->objectinstance; exclude.facenr= shi->vlr->index; - sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao, shi->indirect); + sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao, shi->env, shi->indirect); VECCOPY(sample->co, shi->co); VECCOPY(sample->n, shi->vno); VECCOPY(sample->ao, shi->ao); + VECCOPY(sample->env, shi->env); VECCOPY(sample->indirect, shi->indirect); sample->intensity= MAX3(sample->ao[0], sample->ao[1], sample->ao[2]); + sample->intensity= MAX2(sample->intensity, MAX3(sample->env[0], sample->env[1], sample->env[2])); sample->intensity= MAX2(sample->intensity, MAX3(sample->indirect[0], sample->indirect[1], sample->indirect[2])); sample->dist2= INPR(shi->dxco, shi->dxco) + INPR(shi->dyco, shi->dyco); sample->x= shi->xs; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index ff7d0d90a06..eaafeec3a8a 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -309,6 +309,12 @@ static char *get_pass_name(int passtype, int channel) if(channel==2) return "Color.B"; return "Color.A"; } + if(passtype == SCE_PASS_EMIT) { + if(channel==-1) return "Emit"; + if(channel==0) return "Emit.R"; + if(channel==1) return "Emit.G"; + return "Emit.B"; + } if(passtype == SCE_PASS_DIFFUSE) { if(channel==-1) return "Diffuse"; if(channel==0) return "Diffuse.R"; @@ -333,6 +339,18 @@ static char *get_pass_name(int passtype, int channel) if(channel==1) return "AO.G"; return "AO.B"; } + if(passtype == SCE_PASS_ENVIRONMENT) { + if(channel==-1) return "Environment"; + if(channel==0) return "Environment.R"; + if(channel==1) return "Environment.G"; + return "Environment.B"; + } + if(passtype == SCE_PASS_INDIRECT) { + if(channel==-1) return "Indirect"; + if(channel==0) return "Indirect.R"; + if(channel==1) return "Indirect.G"; + return "Indirect.B"; + } if(passtype == SCE_PASS_REFLECT) { if(channel==-1) return "Reflect"; if(channel==0) return "Reflect.R"; @@ -390,6 +408,9 @@ static int passtype_from_name(char *str) if(strcmp(str, "Color")==0) return SCE_PASS_RGBA; + if(strcmp(str, "Emit")==0) + return SCE_PASS_EMIT; + if(strcmp(str, "Diffuse")==0) return SCE_PASS_DIFFUSE; @@ -402,6 +423,12 @@ static int passtype_from_name(char *str) if(strcmp(str, "AO")==0) return SCE_PASS_AO; + if(strcmp(str, "Environment")==0) + return SCE_PASS_ENVIRONMENT; + + if(strcmp(str, "Indirect")==0) + return SCE_PASS_INDIRECT; + if(strcmp(str, "Reflect")==0) return SCE_PASS_REFLECT; @@ -572,12 +599,18 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int render_layer_add_pass(rr, rl, 3, SCE_PASS_UV); if(srl->passflag & SCE_PASS_RGBA) render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA); + if(srl->passflag & SCE_PASS_EMIT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT); if(srl->passflag & SCE_PASS_DIFFUSE) render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE); if(srl->passflag & SCE_PASS_SPEC) render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC); if(srl->passflag & SCE_PASS_AO) render_layer_add_pass(rr, rl, 3, SCE_PASS_AO); + if(srl->passflag & SCE_PASS_ENVIRONMENT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT); + if(srl->passflag & SCE_PASS_INDIRECT) + render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT); if(srl->passflag & SCE_PASS_SHADOW) render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW); if(srl->passflag & SCE_PASS_REFLECT) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 5bdc1276a91..d35521e92ac 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -1829,7 +1829,7 @@ static float *sphere_sampler(int type, int resol, int thread, int xs, int ys) } } -static void ray_ao_qmc(ShadeInput *shi, float *shadfac) +static void ray_ao_qmc(ShadeInput *shi, float *ao, float *env) { Isect isec; RayHint point_hint; @@ -1845,8 +1845,8 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) int samples=0; int max_samples = R.wrld.aosamp*R.wrld.aosamp; - float dxyview[3], skyadded=0, div; - int aocolor; + float dxyview[3], skyadded=0; + int envcolor; RE_RC_INIT(isec, *shi); isec.orig.ob = shi->obi; @@ -1866,15 +1866,15 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) RE_rayobject_hint_bb( R.raytree, &point_hint, isec.start, isec.start ); isec.hint = &point_hint; - - shadfac[0]= shadfac[1]= shadfac[2]= 0.0f; + zero_v3(ao); + zero_v3(env); /* prevent sky colors to be added for only shadow (shadow becomes alpha) */ - aocolor= R.wrld.aocolor; + envcolor= R.wrld.aocolor; if(shi->mat->mode & MA_ONLYSHADOW) - aocolor= WO_AOPLAIN; + envcolor= WO_AOPLAIN; - if(aocolor == WO_AOSKYTEX) { + if(envcolor == WO_AOSKYTEX) { dxyview[0]= 1.0f/(float)R.wrld.aosamp; dxyview[1]= 1.0f/(float)R.wrld.aosamp; dxyview[2]= 0.0f; @@ -1927,7 +1927,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) if (R.wrld.aomode & WO_AODIST) fac+= exp(-isec.labda*R.wrld.aodistfac); else fac+= 1.0f; } - else if(aocolor!=WO_AOPLAIN) { + else if(envcolor!=WO_AOPLAIN) { float skycol[4]; float skyfac, view[3]; @@ -1936,18 +1936,18 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) view[2]= -dir[2]; normalize_v3(view); - if(aocolor==WO_AOSKYCOL) { + if(envcolor==WO_AOSKYCOL) { skyfac= 0.5*(1.0f+view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]); - shadfac[0]+= (1.0f-skyfac)*R.wrld.horr + skyfac*R.wrld.zenr; - shadfac[1]+= (1.0f-skyfac)*R.wrld.horg + skyfac*R.wrld.zeng; - shadfac[2]+= (1.0f-skyfac)*R.wrld.horb + skyfac*R.wrld.zenb; + env[0]+= (1.0f-skyfac)*R.wrld.horr + skyfac*R.wrld.zenr; + env[1]+= (1.0f-skyfac)*R.wrld.horg + skyfac*R.wrld.zeng; + env[2]+= (1.0f-skyfac)*R.wrld.horb + skyfac*R.wrld.zenb; } else { /* WO_AOSKYTEX */ shadeSkyView(skycol, isec.start, view, dxyview, shi->thread); shadeSunView(skycol, shi->view); - shadfac[0]+= skycol[0]; - shadfac[1]+= skycol[1]; - shadfac[2]+= skycol[2]; + env[0]+= skycol[0]; + env[1]+= skycol[1]; + env[2]+= skycol[2]; } skyadded++; } @@ -1965,29 +1965,27 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) } } - if(aocolor!=WO_AOPLAIN && skyadded) { - div= (1.0f - fac/(float)samples)/((float)skyadded); - - shadfac[0]*= div; // average color times distances/hits formula - shadfac[1]*= div; // average color times distances/hits formula - shadfac[2]*= div; // average color times distances/hits formula - } else { - shadfac[0]= shadfac[1]= shadfac[2]= 1.0f - fac/(float)samples; - } + /* average color times distances/hits formula */ + ao[0]= ao[1]= ao[2]= 1.0f - fac/(float)samples; + + if(envcolor!=WO_AOPLAIN && skyadded) + mul_v3_fl(env, (1.0f - fac/(float)samples)/((float)skyadded)); + else + copy_v3_v3(env, ao); if (qsa) release_thread_qmcsampler(&R, shi->thread, qsa); } /* extern call from shade_lamp_loop, ambient occlusion calculus */ -static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) +static void ray_ao_spheresamp(ShadeInput *shi, float *ao, float *env) { Isect isec; RayHint point_hint; - float *vec, *nrm, div, bias, sh=0.0f; + float *vec, *nrm, bias, sh=0.0f; float maxdist = R.wrld.aodist; float dxyview[3]; - int j= -1, tot, actual=0, skyadded=0, aocolor, resol= R.wrld.aosamp; + int j= -1, tot, actual=0, skyadded=0, envcolor, resol= R.wrld.aosamp; RE_RC_INIT(isec, *shi); isec.orig.ob = shi->obi; @@ -2007,7 +2005,8 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) RE_rayobject_hint_bb( R.raytree, &point_hint, isec.start, isec.start ); isec.hint = &point_hint; - shadfac[0]= shadfac[1]= shadfac[2]= 0.0f; + zero_v3(ao); + zero_v3(env); /* bias prevents smoothed faces to appear flat */ if(shi->vlr->flag & R_SMOOTH) { @@ -2020,9 +2019,9 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) } /* prevent sky colors to be added for only shadow (shadow becomes alpha) */ - aocolor= R.wrld.aocolor; + envcolor= R.wrld.aocolor; if(shi->mat->mode & MA_ONLYSHADOW) - aocolor= WO_AOPLAIN; + envcolor= WO_AOPLAIN; if(resol>32) resol= 32; @@ -2031,7 +2030,7 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) // warning: since we use full sphere now, and dotproduct is below, we do twice as much tot= 2*resol*resol; - if(aocolor == WO_AOSKYTEX) { + if(envcolor == WO_AOSKYTEX) { dxyview[0]= 1.0f/(float)resol; dxyview[1]= 1.0f/(float)resol; dxyview[2]= 0.0f; @@ -2063,7 +2062,7 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) if (R.wrld.aomode & WO_AODIST) sh+= exp(-isec.labda*R.wrld.aodistfac); else sh+= 1.0f; } - else if(aocolor!=WO_AOPLAIN) { + else if(envcolor!=WO_AOPLAIN) { float skycol[4]; float fac, view[3]; @@ -2072,18 +2071,18 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) view[2]= -vec[2]; normalize_v3(view); - if(aocolor==WO_AOSKYCOL) { + if(envcolor==WO_AOSKYCOL) { fac= 0.5*(1.0f+view[0]*R.grvec[0]+ view[1]*R.grvec[1]+ view[2]*R.grvec[2]); - shadfac[0]+= (1.0f-fac)*R.wrld.horr + fac*R.wrld.zenr; - shadfac[1]+= (1.0f-fac)*R.wrld.horg + fac*R.wrld.zeng; - shadfac[2]+= (1.0f-fac)*R.wrld.horb + fac*R.wrld.zenb; + env[0]+= (1.0f-fac)*R.wrld.horr + fac*R.wrld.zenr; + env[1]+= (1.0f-fac)*R.wrld.horg + fac*R.wrld.zeng; + env[2]+= (1.0f-fac)*R.wrld.horb + fac*R.wrld.zenb; } else { /* WO_AOSKYTEX */ shadeSkyView(skycol, isec.start, view, dxyview, shi->thread); shadeSunView(skycol, shi->view); - shadfac[0]+= skycol[0]; - shadfac[1]+= skycol[1]; - shadfac[2]+= skycol[2]; + env[0]+= skycol[0]; + env[1]+= skycol[1]; + env[2]+= skycol[2]; } skyadded++; } @@ -2095,28 +2094,25 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) if(actual==0) sh= 1.0f; else sh = 1.0f - sh/((float)actual); - if(aocolor!=WO_AOPLAIN && skyadded) { - div= sh/((float)skyadded); - - shadfac[0]*= div; // average color times distances/hits formula - shadfac[1]*= div; // average color times distances/hits formula - shadfac[2]*= div; // average color times distances/hits formula - } - else { - shadfac[0]= shadfac[1]= shadfac[2]= sh; - } + /* average color times distances/hits formula */ + ao[0]= ao[1]= ao[2]= sh; + + if(envcolor!=WO_AOPLAIN && skyadded) + mul_v3_fl(env, sh/((float)skyadded)); + else + copy_v3_v3(env, ao); } -void ray_ao(ShadeInput *shi, float *shadfac) +void ray_ao(ShadeInput *shi, float *ao, float *env) { /* Unfortunately, the unusual way that the sphere sampler calculates roughly twice as many * samples as are actually traced, and skips them based on bias and OSA settings makes it very difficult * to reuse code between these two functions. This is the easiest way I can think of to do it * --broken */ if (ELEM(R.wrld.ao_samp_method, WO_AOSAMP_HAMMERSLEY, WO_AOSAMP_HALTON)) - ray_ao_qmc(shi, shadfac); + ray_ao_qmc(shi, ao, env); else if (R.wrld.ao_samp_method == WO_AOSAMP_CONSTANT) - ray_ao_spheresamp(shi, shadfac); + ray_ao_spheresamp(shi, ao, env); } static void ray_shadow_jittered_coords(ShadeInput *shi, int max, float jitco[RE_MAX_OSA][3], int *totjitco) diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index e99d2bfa0f6..dec826faa65 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -459,6 +459,9 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, col= shr->col; pixsize= 4; break; + case SCE_PASS_EMIT: + col= shr->emit; + break; case SCE_PASS_DIFFUSE: col= shr->diff; break; @@ -471,6 +474,12 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, case SCE_PASS_AO: col= shr->ao; break; + case SCE_PASS_ENVIRONMENT: + col= shr->env; + break; + case SCE_PASS_INDIRECT: + col= shr->indirect; + break; case SCE_PASS_REFLECT: col= shr->refl; break; @@ -557,6 +566,9 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult col= shr->col; pixsize= 4; break; + case SCE_PASS_EMIT: + col= shr->emit; + break; case SCE_PASS_DIFFUSE: col= shr->diff; break; @@ -569,6 +581,12 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult case SCE_PASS_AO: col= shr->ao; break; + case SCE_PASS_ENVIRONMENT: + col= shr->env; + break; + case SCE_PASS_INDIRECT: + col= shr->indirect; + break; case SCE_PASS_REFLECT: col= shr->refl; break; @@ -2117,10 +2135,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int if(bs->type==RE_BAKE_AO) { ambient_occlusion(shi); - if(R.r.bake_flag & R_BAKE_NORMALIZE) - VECCOPY(shr.combined, shi->ao) - else - ambient_occlusion_to_diffuse(shi, shr.combined); + VECCOPY(shr.combined, shi->ao) } else { if (bs->type==RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */ diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index fd1e27ab28a..38241878300 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -1319,11 +1319,11 @@ void shade_samples_do_AO(ShadeSample *ssamp) if(!(R.r.mode & R_RAYTRACE) && !(R.wrld.ao_gather_method == WO_AOGATHER_APPROX)) return; - if(R.wrld.mode & WO_AMB_OCC) { + if(R.wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) { shi= &ssamp->shi[0]; - if(((shi->passflag & SCE_PASS_COMBINED) && (shi->combinedflag & SCE_PASS_AO)) - || (shi->passflag & SCE_PASS_AO)) + if(((shi->passflag & SCE_PASS_COMBINED) && (shi->combinedflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) + || (shi->passflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) for(sample=0, shi= ssamp->shi; sample<ssamp->tot; shi++, sample++) if(!(shi->mode & MA_SHLESS)) ambient_occlusion(shi); /* stores in shi->ao[] */ diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index e9386bb0d94..4192966b1fa 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -1013,41 +1013,69 @@ void ambient_occlusion(ShadeInput *shi) if((R.wrld.ao_gather_method == WO_AOGATHER_APPROX) && shi->mat->amb!=0.0f) sample_occ(&R, shi); else if((R.r.mode & R_RAYTRACE) && shi->mat->amb!=0.0f) - ray_ao(shi, shi->ao); + ray_ao(shi, shi->ao, shi->env); else shi->ao[0]= shi->ao[1]= shi->ao[2]= 1.0f; } /* wrld mode was checked for */ -void ambient_occlusion_to_diffuse(ShadeInput *shi, float *diff) +static void ambient_occlusion_apply(ShadeInput *shi, ShadeResult *shr) { - if((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX) { - if(shi->amb!=0.0f) { - float f= R.wrld.aoenergy*shi->amb; - - if (R.wrld.aomix==WO_AOADDSUB) { - diff[0] = 2.0f*shi->ao[0]-1.0f; - diff[1] = 2.0f*shi->ao[1]-1.0f; - diff[2] = 2.0f*shi->ao[2]-1.0f; - } - else if (R.wrld.aomix==WO_AOSUB) { - diff[0] = shi->ao[0]-1.0f; - diff[1] = shi->ao[1]-1.0f; - diff[2] = shi->ao[2]-1.0f; - } - else { - VECCOPY(diff, shi->ao); - } - - VECMUL(diff, f); - madd_v3_v3fl(diff, shi->indirect, R.wrld.ao_indirect_energy*shi->amb); + float f= R.wrld.aoenergy; + float tmp[3], tmpspec[3]; + + if(!((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX)) + return; + if(f == 0.0f) + return; + + if(R.wrld.aomix==WO_AOADD) { + shr->combined[0] += shi->ao[0]*shi->r*shi->refl*f; + shr->combined[1] += shi->ao[1]*shi->g*shi->refl*f; + shr->combined[2] += shi->ao[2]*shi->b*shi->refl*f; + } + else if(R.wrld.aomix==WO_AOMUL) { + mul_v3_v3v3(tmp, shr->combined, shi->ao); + mul_v3_v3v3(tmpspec, shr->spec, shi->ao); + + if(f == 1.0f) { + copy_v3_v3(shr->combined, tmp); + copy_v3_v3(shr->spec, tmpspec); + } + else { + interp_v3_v3v3(shr->combined, shr->combined, tmp, f); + interp_v3_v3v3(shr->spec, shr->spec, tmpspec, f); } - else - diff[0]= diff[1]= diff[2]= 0.0f; } - else - diff[0]= diff[1]= diff[2]= 0.0f; +} + +static void environment_lighting_apply(ShadeInput *shi, ShadeResult *shr) +{ + float f= R.wrld.ao_env_energy*shi->amb; + + if(!((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX)) + return; + if(f == 0.0f) + return; + + shr->combined[0] += shi->env[0]*shi->r*shi->refl*f; + shr->combined[1] += shi->env[1]*shi->g*shi->refl*f; + shr->combined[2] += shi->env[2]*shi->b*shi->refl*f; +} + +static void indirect_lighting_apply(ShadeInput *shi, ShadeResult *shr) +{ + float f= R.wrld.ao_indirect_energy; + + if(!((R.r.mode & R_RAYTRACE) || R.wrld.ao_gather_method == WO_AOGATHER_APPROX)) + return; + if(f == 0.0f) + return; + + shr->combined[0] += shi->indirect[0]*shi->r*shi->refl*f; + shr->combined[1] += shi->indirect[1]*shi->g*shi->refl*f; + shr->combined[2] += shi->indirect[2]*shi->b*shi->refl*f; } /* result written in shadfac */ @@ -1510,7 +1538,7 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr) } /* quite disputable this... also note it doesn't mirror-raytrace */ - if((R.wrld.mode & WO_AMB_OCC) && shi->amb!=0.0f) { + if((R.wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && shi->amb!=0.0f) { float f; f= 1.0f - shi->ao[0]; @@ -1520,12 +1548,8 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr) shr->alpha += f; shr->alpha *= f; } - else if(R.wrld.aomix==WO_AOSUB) { - shr->alpha += f; - } - else { + else if(R.wrld.aomix==WO_AOMUL) { shr->alpha *= f; - shr->alpha += f; } } } @@ -1600,25 +1624,26 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) } if( (ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL ) { // vertexcolor light - shr->diff[0]= shi->r*(shi->emit+shi->vcol[0]); - shr->diff[1]= shi->g*(shi->emit+shi->vcol[1]); - shr->diff[2]= shi->b*(shi->emit+shi->vcol[2]); + shr->emit[0]= shi->r*(shi->emit+shi->vcol[0]); + shr->emit[1]= shi->g*(shi->emit+shi->vcol[1]); + shr->emit[2]= shi->b*(shi->emit+shi->vcol[2]); } else { - shr->diff[0]= shi->r*shi->emit; - shr->diff[1]= shi->g*shi->emit; - shr->diff[2]= shi->b*shi->emit; + shr->emit[0]= shi->r*shi->emit; + shr->emit[1]= shi->g*shi->emit; + shr->emit[2]= shi->b*shi->emit; } - VECCOPY(shr->shad, shr->diff); /* AO pass */ - if(R.wrld.mode & WO_AMB_OCC) { - if(((passflag & SCE_PASS_COMBINED) && (shi->combinedflag & SCE_PASS_AO)) - || (passflag & SCE_PASS_AO)) { + if(R.wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) { + if(((passflag & SCE_PASS_COMBINED) && (shi->combinedflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) + || (passflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) { /* AO was calculated for scanline already */ if(shi->depth) ambient_occlusion(shi); VECCOPY(shr->ao, shi->ao); + VECCOPY(shr->env, shi->env); // XXX multiply + VECCOPY(shr->indirect, shi->indirect); // XXX multiply } } @@ -1727,6 +1752,19 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) /* from now stuff everything in shr->combined: ambient, AO, radio, ramps, exposure */ if(!(ma->sss_flag & MA_DIFF_SSS) || !sss_pass_done(&R, ma)) { + /* add AO in combined? */ + if(R.wrld.mode & WO_AMB_OCC) + if(shi->combinedflag & SCE_PASS_AO) + ambient_occlusion_apply(shi, shr); + + if(R.wrld.mode & WO_ENV_LIGHT) + if(shi->combinedflag & SCE_PASS_ENVIRONMENT) + environment_lighting_apply(shi, shr); + + if(R.wrld.mode & WO_INDIRECT_LIGHT) + if(shi->combinedflag & SCE_PASS_INDIRECT) + indirect_lighting_apply(shi, shr); + shr->combined[0]+= shi->ambr; shr->combined[1]+= shi->ambg; shr->combined[2]+= shi->ambb; @@ -1738,22 +1776,6 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) shr->combined[2]+= shi->b*shi->amb*shi->rad[2]; }*/ - /* add AO in combined? */ - if(R.wrld.mode & WO_AMB_OCC) { - if(shi->combinedflag & SCE_PASS_AO) { - float aodiff[3]; - ambient_occlusion_to_diffuse(shi, aodiff); - - shr->combined[0] += shi->r*aodiff[0]; - shr->combined[1] += shi->g*aodiff[1]; - shr->combined[2] += shi->b*aodiff[2]; - - if (shr->combined[0] < 0.f) shr->combined[0]= 0.f; - if (shr->combined[1] < 0.f) shr->combined[1]= 0.f; - if (shr->combined[2] < 0.f) shr->combined[2]= 0.f; - } - } - if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shr->combined, shi); } @@ -1775,10 +1797,12 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) } - /* and add spec */ + /* and add emit and spec */ + if(shi->combinedflag & SCE_PASS_EMIT) + VECADD(shr->combined, shr->combined, shr->emit); if(shi->combinedflag & SCE_PASS_SPEC) VECADD(shr->combined, shr->combined, shr->spec); - + /* modulate by the object color */ if((ma->shade_flag & MA_OBCOLOR) && shi->obr->ob) { if(!(ma->sss_flag & MA_DIFF_SSS) || !sss_pass_done(&R, ma)) { diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c index 2b1c121539e..279d53d050c 100644 --- a/source/blender/render/intern/source/strand.c +++ b/source/blender/render/intern/source/strand.c @@ -222,6 +222,8 @@ void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float t, Sha interpolate_vec3(shr1->nor, shr2->nor, t, negt, shr->nor); normalize_v3(shr->nor); } + if(addpassflag & SCE_PASS_EMIT) + interpolate_vec3(shr1->emit, shr2->emit, t, negt, shr->emit); if(addpassflag & SCE_PASS_DIFFUSE) interpolate_vec3(shr1->diff, shr2->diff, t, negt, shr->diff); if(addpassflag & SCE_PASS_SPEC) @@ -230,6 +232,10 @@ void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float t, Sha interpolate_vec3(shr1->shad, shr2->shad, t, negt, shr->shad); if(addpassflag & SCE_PASS_AO) interpolate_vec3(shr1->ao, shr2->ao, t, negt, shr->ao); + if(addpassflag & SCE_PASS_ENVIRONMENT) + interpolate_vec3(shr1->env, shr2->env, t, negt, shr->env); + if(addpassflag & SCE_PASS_INDIRECT) + interpolate_vec3(shr1->indirect, shr2->indirect, t, negt, shr->indirect); if(addpassflag & SCE_PASS_REFLECT) interpolate_vec3(shr1->refl, shr2->refl, t, negt, shr->refl); if(addpassflag & SCE_PASS_REFRACT) @@ -963,6 +969,7 @@ StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm, mesh->totface= totface; mesh->face= MEM_callocN(sizeof(int)*4*mesh->totface, "StrandSurfFaces"); mesh->ao= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfAO"); + mesh->env= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfEnv"); mesh->indirect= MEM_callocN(sizeof(float)*3*mesh->totvert, "StrandSurfIndirect"); BLI_addtail(&re->strandsurface, mesh); } @@ -1002,6 +1009,7 @@ void free_strand_surface(Render *re) if(mesh->prevco) MEM_freeN(mesh->prevco); if(mesh->nextco) MEM_freeN(mesh->nextco); if(mesh->ao) MEM_freeN(mesh->ao); + if(mesh->env) MEM_freeN(mesh->env); if(mesh->indirect) MEM_freeN(mesh->indirect); if(mesh->face) MEM_freeN(mesh->face); } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index ac3474e51e5..484dbdd37a3 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -3516,6 +3516,9 @@ void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) col= shr->col; pixsize= 4; break; + case SCE_PASS_EMIT: + col= shr->emit; + break; case SCE_PASS_DIFFUSE: col= shr->diff; break; @@ -3528,6 +3531,12 @@ void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) case SCE_PASS_AO: col= shr->ao; break; + case SCE_PASS_ENVIRONMENT: + col= shr->env; + break; + case SCE_PASS_INDIRECT: + col= shr->indirect; + break; case SCE_PASS_REFLECT: col= shr->refl; break; @@ -3615,6 +3624,9 @@ void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alph fp= rpass->rect + 4*offset; addAlphaOverFloat(fp, shr->col); break; + case SCE_PASS_EMIT: + col= shr->emit; + break; case SCE_PASS_DIFFUSE: col= shr->diff; break; @@ -3627,6 +3639,12 @@ void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alph case SCE_PASS_AO: col= shr->ao; break; + case SCE_PASS_ENVIRONMENT: + col= shr->env; + break; + case SCE_PASS_INDIRECT: + col= shr->indirect; + break; case SCE_PASS_REFLECT: col= shr->refl; break; @@ -3851,6 +3869,9 @@ static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassf if(addpassflag & SCE_PASS_NORMAL) addvecmul(samp_shr->nor, shr->nor, fac); + if(addpassflag & SCE_PASS_EMIT) + addvecmul(samp_shr->emit, shr->emit, fac); + if(addpassflag & SCE_PASS_DIFFUSE) addvecmul(samp_shr->diff, shr->diff, fac); @@ -3863,6 +3884,12 @@ static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassf if(addpassflag & SCE_PASS_AO) addvecmul(samp_shr->ao, shr->ao, fac); + if(addpassflag & SCE_PASS_ENVIRONMENT) + addvecmul(samp_shr->env, shr->env, fac); + + if(addpassflag & SCE_PASS_INDIRECT) + addvecmul(samp_shr->indirect, shr->indirect, fac); + if(addpassflag & SCE_PASS_REFLECT) addvecmul(samp_shr->refl, shr->refl, fac); |