Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Fri, 8 Jun 2018 06:10:35 +0000 (08:10 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 8 Jun 2018 06:10:35 +0000 (08:10 +0200)
82 files changed:
1  2 
source/blender/blenfont/intern/blf.c
source/blender/blenfont/intern/blf_font.c
source/blender/blenfont/intern/blf_glyph.c
source/blender/blenfont/intern/blf_internal_types.h
source/blender/collada/AnimationExporter.cpp
source/blender/collada/AnimationExporter.h
source/blender/collada/AnimationImporter.cpp
source/blender/collada/ArmatureExporter.cpp
source/blender/collada/ArmatureImporter.cpp
source/blender/collada/ArmatureImporter.h
source/blender/collada/ControllerExporter.cpp
source/blender/collada/DocumentExporter.cpp
source/blender/collada/DocumentImporter.cpp
source/blender/collada/DocumentImporter.h
source/blender/collada/EffectExporter.cpp
source/blender/collada/EffectExporter.h
source/blender/collada/GeometryExporter.cpp
source/blender/collada/GeometryExporter.h
source/blender/collada/ImageExporter.cpp
source/blender/collada/ImageExporter.h
source/blender/collada/InstanceWriter.cpp
source/blender/collada/LightExporter.cpp
source/blender/collada/MeshImporter.cpp
source/blender/collada/MeshImporter.h
source/blender/collada/SceneExporter.cpp
source/blender/collada/SceneExporter.h
source/blender/collada/SkinInfo.cpp
source/blender/collada/SkinInfo.h
source/blender/collada/TransformWriter.cpp
source/blender/collada/collada_internal.h
source/blender/collada/collada_utils.cpp
source/blender/collada/collada_utils.h
source/blender/ikplugin/intern/ikplugin_api.c
source/blender/ikplugin/intern/itasc_plugin.cpp
source/blender/nodes/composite/node_composite_tree.c
source/blender/nodes/composite/nodes/node_composite_image.c
source/blender/nodes/intern/node_exec.c
source/blender/nodes/intern/node_socket.c
source/blender/nodes/shader/node_shader_tree.c
source/blender/nodes/shader/node_shader_util.c
source/blender/nodes/shader/nodes/node_shader_brightness.c
source/blender/nodes/shader/nodes/node_shader_bump.c
source/blender/nodes/shader/nodes/node_shader_curves.c
source/blender/nodes/shader/nodes/node_shader_fresnel.c
source/blender/nodes/shader/nodes/node_shader_gamma.c
source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
source/blender/nodes/shader/nodes/node_shader_invert.c
source/blender/nodes/shader/nodes/node_shader_mapping.c
source/blender/nodes/shader/nodes/node_shader_math.c
source/blender/nodes/shader/nodes/node_shader_mixRgb.c
source/blender/nodes/shader/nodes/node_shader_normal.c
source/blender/nodes/shader/nodes/node_shader_output_world.c
source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
source/blender/nodes/shader/nodes/node_shader_squeeze.c
source/blender/nodes/shader/nodes/node_shader_tex_brick.c
source/blender/nodes/shader/nodes/node_shader_tex_coord.c
source/blender/nodes/shader/nodes/node_shader_tex_environment.c
source/blender/nodes/shader/nodes/node_shader_valToRgb.c
source/blender/nodes/shader/nodes/node_shader_vectMath.c
source/blender/nodes/shader/nodes/node_shader_vectTransform.c
source/blender/nodes/texture/node_texture_tree.c
source/blender/nodes/texture/node_texture_util.c
source/blender/nodes/texture/nodes/node_texture_image.c
source/blender/nodes/texture/nodes/node_texture_proc.c
source/blender/nodes/texture/nodes/node_texture_texture.c
source/blender/physics/intern/BPH_mass_spring.cpp
source/blender/physics/intern/hair_volume.cpp
source/blender/physics/intern/implicit.h
source/blender/render/CMakeLists.txt
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/include/initrender.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/include/zbuf.h
source/blender/render/intern/source/external_engine.c
source/blender/render/intern/source/imagetexture.c
source/blender/render/intern/source/initrender.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/pointdensity.c
source/blender/render/intern/source/render_result.c
source/blender/render/intern/source/render_texture.c
source/blender/render/intern/source/zbuf.c

Simple merge
@@@ -204,11 -174,9 +204,11 @@@ typedef struct FontBLF 
  
        /* angle in radians. */
        float angle;
-       
 +#if 0 /* BLF_BLUR_ENABLE */
        /* blur: 3 or 5 large kernel */
        int blur;
 +#endif
  
        /* shadow level. */
        int shadow;
@@@ -728,9 -728,9 +728,9 @@@ void AnimationExporter::sample_and_writ
                dae_baked_animation(fra, ob_arm, bone);
        }
  
-       if (flag & ARM_RESTPOS) 
+       if (flag & ARM_RESTPOS)
                arm->flag = flag;
 -      BKE_pose_where_is(scene, ob_arm);
 +      BKE_pose_where_is(depsgraph, scene, ob_arm);
  }
  
  void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone)
@@@ -1315,18 -1315,17 +1315,18 @@@ std::string AnimationExporter::create_4
                float frame = *it;
  
                float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
 -              bc_update_scene(scene, ctime);
 +              bc_update_scene(depsgraph, scene, ctime);
                if (is_bone_animation) {
 +
                        if (pchan->flag & POSE_CHAIN) {
                                enable_fcurves(ob->adt->action, NULL);
 -                              BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
 -                              BKE_pose_where_is(scene, ob);
 +                              BKE_animsys_evaluate_animdata(depsgraph, scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
 +                              BKE_pose_where_is(depsgraph, scene, ob);
                        }
                        else {
 -                              BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
 +                              BKE_pose_where_is_bone(depsgraph, scene, ob, pchan, ctime, 1);
                        }
-                       
                        // compute bone local mat
                        if (bone->parent) {
                                invert_m4_m4(ipar, parchan->pose_mat);
@@@ -1842,9 -1841,9 +1842,9 @@@ void AnimationExporter::sample_and_writ
        // exit rest position
        if (flag & ARM_RESTPOS) {
                arm->flag &= ~ARM_RESTPOS;
 -              BKE_pose_where_is(scene, ob_arm);
 +              BKE_pose_where_is(depsgraph, scene, ob_arm);
        }
-       //v array will hold all values which will be exported. 
+       //v array will hold all values which will be exported.
        if (fra.size()) {
                float *values = (float *)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
                sample_animation(values, fra, transform_type, bone, ob_arm, pchan);
        }
  
        // restore restpos
-       if (flag & ARM_RESTPOS) 
+       if (flag & ARM_RESTPOS)
                arm->flag = flag;
 -      BKE_pose_where_is(scene, ob_arm);
 +      BKE_pose_where_is(depsgraph, scene, ob_arm);
  }
  
  void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
@@@ -99,9 -97,10 +99,9 @@@ public
        }
  
        bool exportAnimations(Scene *sce);
 -
        // called for each exported object
-       void operator() (Object *ob); 
-       
+       void operator() (Object *ob);
  protected:
        const ExportSettings *export_settings;
  
@@@ -117,8 -117,11 +117,8 @@@ bool ArmatureExporter::add_instance_con
                write_bone_URLs(ins, ob_arm, bone);
        }
  
 -      InstanceWriter::add_material_bindings(ins.getBindMaterial(),
 -              ob,
 -              this->export_settings->active_uv_only,
 -              this->export_settings->export_texture_type);
 +      InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
-               
        ins.add();
        return true;
  }
@@@ -55,13 -54,12 +55,13 @@@ static const char *bc_get_joint_name(T 
  }
  
  
 -ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, const ImportSettings *import_settings) :
 +ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, ViewLayer *view_layer, const ImportSettings *import_settings) :
        TransformReader(conv),
        scene(sce),
 +      view_layer(view_layer),
        unit_converter(conv),
        import_settings(import_settings),
-       empty(NULL), 
+       empty(NULL),
        mesh_importer(mesh) {
  }
  
@@@ -410,8 -408,8 +410,8 @@@ void ArmatureImporter::set_euler_rotmod
  Object *ArmatureImporter::get_empty_for_leaves()
  {
        if (empty) return empty;
-       
 -      empty = bc_add_object(scene, OB_EMPTY, NULL);
 +      empty = bc_add_object(scene, view_layer, OB_EMPTY, NULL);
        empty->empty_drawtype = OB_EMPTY_SPHERE;
  
        return empty;
@@@ -98,8 -98,11 +98,8 @@@ bool ControllerExporter::add_instance_c
                write_bone_URLs(ins, ob_arm, bone);
        }
  
 -      InstanceWriter::add_material_bindings(ins.getBindMaterial(),
 -                  ob,
 -                      this->export_settings->active_uv_only,
 -                      this->export_settings->export_texture_type);
 +      InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
-               
        ins.add();
        return true;
  }
@@@ -292,9 -293,9 +292,9 @@@ int DocumentExporter::exportCurrentScen
        // <library_controllers>
        ArmatureExporter arm_exporter(writer, this->export_settings);
        ControllerExporter controller_exporter(writer, this->export_settings);
-       if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings->include_shapekeys) 
+       if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings->include_shapekeys)
        {
 -              controller_exporter.export_controllers(sce);
 +              controller_exporter.export_controllers(depsgraph, sce);
        }
  
        // <library_visual_scenes>
  
        if (this->export_settings->include_animations) {
                // <library_animations>
 -              AnimationExporter ae(writer, this->export_settings);
 +              AnimationExporter ae(depsgraph, writer, this->export_settings);
                ae.exportAnimations(sce);
        }
 -      se.exportScene(C, sce);
 +      se.exportScene(C, depsgraph, sce);
-       
        // <scene>
        std::string scene_name(translate_id(id_name(sce)));
        COLLADASW::Scene scene(writer, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING,
@@@ -270,9 -274,9 +270,9 @@@ void DocumentImporter::finish(
                }
                libnode_ob.clear();
  
 -              DAG_relations_tag_update(bmain);
 +              DEG_relations_tag_update(bmain);
        }
-       
        bc_match_scale(objects_to_scale, unit_converter, !this->import_settings->import_units);
  
        delete objects_to_scale;
@@@ -767,14 -797,10 +767,14 @@@ void DocumentImporter::write_profile_CO
  {
        COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
  
-       
 +      // TODO: add back texture and extended material parameter support
++
        // blinn
        if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
 +#if 0
                ma->spec_shader = MA_SPEC_BLINN;
                ma->spec = ef->getShininess().getFloatValue();
 +#endif
        }
        // phong
        else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
        }
        // default - lambert
        else {
 +#if 0
                ma->diff_shader = MA_DIFF_LAMBERT;
                fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
 +#endif
        }
        // reflectivity
 -      ma->ray_mirror = ef->getReflectivity().getFloatValue();
 +      ma->metallic = ef->getReflectivity().getFloatValue();
        // index of refraction
 +#if 0
        ma->ang = ef->getIndexOfRefraction().getFloatValue();
-       
 +#endif
 -      int i = 0;
        COLLADAFW::Color col;
-       
 -      MTex *mtex = NULL;
 -      TexIndexTextureArrayMap texindex_texarray_map;
        // DIFFUSE
        // color
        if (ef->getDiffuse().isColor()) {
        }
        // texture
        else if (ef->getDiffuse().isTexture()) {
-               COLLADAFW::Texture ctex = ef->getDiffuse().getTexture(); 
 +#if 0
 -              mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
 -              if (mtex != NULL) {
 -                      mtex->mapto = MAP_COL;
 -                      ma->texact = (int)i;
 -                      i++;
 -              }
+               COLLADAFW::Texture ctex = ef->getDiffuse().getTexture();
 +#endif
        }
        // AMBIENT
        // color
        }
        // texture
        else if (ef->getAmbient().isTexture()) {
-               COLLADAFW::Texture ctex = ef->getAmbient().getTexture(); 
 +#if 0
 -              mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
 -              if (mtex != NULL) {
 -                      mtex->mapto = MAP_AMB;
 -                      i++;
 -              }
+               COLLADAFW::Texture ctex = ef->getAmbient().getTexture();
 +#endif
        }
        // SPECULAR
        // color
        }
        // texture
        else if (ef->getSpecular().isTexture()) {
-               COLLADAFW::Texture ctex = ef->getSpecular().getTexture(); 
 +#if 0
 -              mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
 -              if (mtex != NULL) {
 -                      mtex->mapto = MAP_SPEC;
 -                      i++;
 -              }
+               COLLADAFW::Texture ctex = ef->getSpecular().getTexture();
 +#endif
        }
        // REFLECTIVE
        // color
        }
        // texture
        else if (ef->getReflective().isTexture()) {
-               COLLADAFW::Texture ctex = ef->getReflective().getTexture(); 
 +#if 0
 -              mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
 -              if (mtex != NULL) {
 -                      mtex->mapto = MAP_REF;
 -                      i++;
 -              }
+               COLLADAFW::Texture ctex = ef->getReflective().getTexture();
 +#endif
        }
  
        // EMISSION
        }
        // texture
        else if (ef->getEmission().isTexture()) {
-               COLLADAFW::Texture ctex = ef->getEmission().getTexture(); 
 +#if 0
 -              mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
 -              if (mtex != NULL) {
 -                      mtex->mapto = MAP_EMIT;
 -                      i++;
 -              }
+               COLLADAFW::Texture ctex = ef->getEmission().getTexture();
 +#endif
        }
  
        // TRANSPARENT
@@@ -77,8 -77,9 +77,8 @@@ public
        Object* create_instance_node(Object*, COLLADAFW::Node*, COLLADAFW::Node*, Scene*, bool);
        void create_constraints(ExtraTags *et, Object *ob);
        std::vector<Object *> *write_node(COLLADAFW::Node*, COLLADAFW::Node*, Scene*, Object*, bool);
 -      MTex* create_texture(COLLADAFW::EffectCommon*, COLLADAFW::Texture&, Material*, int, TexIndexTextureArrayMap&);
        void write_profile_COMMON(COLLADAFW::EffectCommon*, Material*);
-       
        void translate_anim_recursive(COLLADAFW::Node*, COLLADAFW::Node*, Object*);
  
        /**
@@@ -49,20 -48,9 +49,20 @@@ extern "C" 
        #include "BKE_material.h"
  }
  
 -EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) {
 +// OB_MESH is assumed
 +static std::string getActiveUVLayerName(Object *ob)
 +{
 +      Mesh *me = (Mesh *)ob->data;
 +
 +      int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
 +      if (num_layers)
 +              return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
-               
++
 +      return "";
  }
  
 +EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) {
 +}
  
  bool EffectsExporter::hasEffects(Scene *sce)
  {
@@@ -100,17 -138,106 +100,17 @@@ void EffectsExporter::writeLambert(COLL
        ep.setShaderType(COLLADASW::EffectProfile::LAMBERT);
  }
  
 -void EffectsExporter::writePhong(COLLADASW::EffectProfile &ep, Material *ma)
 -{
 -      COLLADASW::ColorOrTexture cot;
 -      ep.setShaderType(COLLADASW::EffectProfile::PHONG);
 -      // shininess
 -      ep.setShininess(ma->har, false, "shininess");
 -      // specular
 -      cot = getcol(ma->specr, ma->specg, ma->specb, 1.0f);
 -      ep.setSpecular(cot, false, "specular");
 -}
 -
 -void EffectsExporter::writeTextures(
 -        COLLADASW::EffectProfile &ep,
 -        std::string &key,
 -        COLLADASW::Sampler *sampler,
 -        MTex *t, Image *ima,
 -        std::string &uvname )
 -{
 -      // Image not set for texture
 -      if (!ima) return;
 -
 -      // color
 -      if (t->mapto & MAP_COL) {
 -              ep.setDiffuse(createTexture(ima, uvname, sampler), false, "diffuse");
 -      }
 -      // ambient
 -      if (t->mapto & MAP_AMB) {
 -              ep.setAmbient(createTexture(ima, uvname, sampler), false, "ambient");
 -      }
 -      // specular
 -      if (t->mapto & (MAP_SPEC | MAP_COLSPEC)) {
 -              ep.setSpecular(createTexture(ima, uvname, sampler), false, "specular");
 -      }
 -      // emission
 -      if (t->mapto & MAP_EMIT) {
 -              ep.setEmission(createTexture(ima, uvname, sampler), false, "emission");
 -      }
 -      // reflective
 -      if (t->mapto & MAP_REF) {
 -              ep.setReflective(createTexture(ima, uvname, sampler));
 -      }
 -      // alpha
 -      if (t->mapto & MAP_ALPHA) {
 -              ep.setTransparent(createTexture(ima, uvname, sampler));
 -      }
 -      // extension:
 -      // Normal map --> Must be stored with <extra> tag as different technique,
 -      // since COLLADA doesn't support normal maps, even in current COLLADA 1.5.
 -      if (t->mapto & MAP_NORM) {
 -              COLLADASW::Texture texture(key);
 -              texture.setTexcoord(uvname);
 -              texture.setSampler(*sampler);
 -              // technique FCOLLADA, with the <bump> tag, is most likely the best understood,
 -              // most widespread de-facto standard.
 -              texture.setProfileName("FCOLLADA");
 -              texture.setChildElementName("bump");
 -              ep.addExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture));
 -      }
 -}
 -
  void EffectsExporter::operator()(Material *ma, Object *ob)
  {
 -      // create a list of indices to textures of type TEX_IMAGE
 -      std::vector<int> tex_indices;
 -      createTextureIndices(ma, tex_indices);
 +      // TODO: add back texture and extended material parameter support
  
        openEffect(translate_id(id_name(ma)) + "-effect");
-       
        COLLADASW::EffectProfile ep(mSW);
        ep.setProfileType(COLLADASW::EffectProfile::COMMON);
        ep.openProfile();
 -      // set shader type - one of three blinn, phong or lambert
 -      if (ma->spec > 0.0f) {
 -              if (ma->spec_shader == MA_SPEC_BLINN) {
 -                      writeBlinn(ep, ma);
 -              }
 -              else {
 -                      // \todo figure out handling of all spec+diff shader combos blender has, for now write phong
 -                      // for now set phong in case spec shader is not blinn
 -                      writePhong(ep, ma);
 -              }
 -      }
 -      else {
 -              if (ma->diff_shader == MA_DIFF_LAMBERT) {
 -                      writeLambert(ep, ma);
 -              }
 -              else {
 -                      // \todo figure out handling of all spec+diff shader combos blender has, for now write phong
 -                      writePhong(ep, ma);
 -              }
 -      }
 -
 -      // index of refraction
 -      if (ma->mode & MA_RAYTRANSP) {
 -              ep.setIndexOfRefraction(ma->ang, false, "index_of_refraction");
 -      }
 -      else {
 -              ep.setIndexOfRefraction(1.0f, false, "index_of_refraction");
 -      }
 +      writeLambert(ep, ma);
-       
        COLLADASW::ColorOrTexture cot;
  
        // transparency
@@@ -48,20 -48,24 +48,20 @@@ class EffectsExporter: COLLADASW::Libra
  public:
        EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
        void exportEffects(Scene *sce);
 +
        void operator()(Material *ma, Object *ob);
-       
        COLLADASW::ColorOrTexture createTexture(Image *ima,
                                                                                        std::string& uv_layer_name,
                                                                                        COLLADASW::Sampler *sampler
                                                                                        /*COLLADASW::Surface *surface*/);
-       
        COLLADASW::ColorOrTexture getcol(float r, float g, float b, float a);
  private:
 -      /** Fills the array of mtex indices which have image. Used for exporting images. */
 -      void createTextureIndices(Material *ma, std::vector<int> &indices);
 -
 -      void writeBlinn(COLLADASW::EffectProfile &ep, Material *ma);
        void writeLambert(COLLADASW::EffectProfile &ep, Material *ma);
 -      void writePhong(COLLADASW::EffectProfile &ep, Material *ma);
        void writeTextures(COLLADASW::EffectProfile &ep,
                        std::string &key,
-                       COLLADASW::Sampler *sampler, 
+                       COLLADASW::Sampler *sampler,
                        MTex *t, Image *ima,
                        std::string &uvname );
  
@@@ -77,7 -77,7 +77,7 @@@ void GeometryExporter::operator()(Objec
  #endif
  
        bool use_instantiation = this->export_settings->use_object_instantiation;
-       Mesh *me = bc_get_mesh_copy(mDepsgraph, mScene, 
 -      Mesh *me = bc_get_mesh_copy( mScene,
++      Mesh *me = bc_get_mesh_copy(mDepsgraph, mScene,
                                        ob,
                                        this->export_settings->export_mesh_type,
                                        this->export_settings->apply_modifiers,
                        }
                }
                else {
 -                      bool all_uv_layers = !this->export_settings->active_uv_only;
 -                      std::set<Image *> uv_image_set = bc_getUVImages(ob, all_uv_layers);
 -                      createPolylists(uv_image_set, has_uvs, has_color, ob, me, geom_id, norind);
 +                      createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
                }
        }
-       
        closeMesh();
-       
        if (me->flag & ME_TWOSIDED) {
                mSW->appendTextBlock("<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>");
        }
@@@ -220,18 -229,20 +220,18 @@@ void GeometryExporter::export_key_mesh(
  
        //createLooseEdgeList(ob, me, geom_id, norind);
  
-       // XXX slow             
+       // XXX slow
 -      if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
 +      if (ob->totcol) {
                for (int a = 0; a < ob->totcol; a++) {
                        createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
                }
        }
        else {
 -              bool all_uv_layers = !this->export_settings->active_uv_only;
 -              std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
 -              createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
 +              createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
        }
-       
        closeMesh();
-       
        if (me->flag & ME_TWOSIDED) {
                mSW->appendTextBlock("<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>");
        }
@@@ -330,32 -381,33 +330,32 @@@ void GeometryExporter::createPolylist(s
                fprintf(stderr, "%s: material with index %d is not used.\n", id_name(ob).c_str(), material_index);
                return;
        }
-               
        Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL;
 -      COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW);
 -
 +      COLLADASW::Polylist polylist(mSW);
-               
        // sets count attribute in <polylist>
 -      facelist->setCount(faces_in_polylist);
 +      polylist.setCount(faces_in_polylist);
-               
        // sets material name
        if (ma) {
                std::string material_id = get_material_id(ma);
                std::ostringstream ostr;
                ostr << translate_id(material_id);
 -              facelist->setMaterial(ostr.str());
 +              polylist.setMaterial(ostr.str());
        }
-                       
 -      COLLADASW::InputList &til = facelist->getInputList();
 +      COLLADASW::InputList &til = polylist.getInputList();
-               
-       // creates <input> in <polylist> for vertices 
+       // creates <input> in <polylist> for vertices
        COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
-               
        // creates <input> in <polylist> for normals
        COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1);
-               
        til.push_back(input1);
        til.push_back(input2);
-               
        // if mesh has uv coords writes <input> for TEXCOORD
        int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
        int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-1;
                        map_index++;
                }
        }
-               
 +      // sets <vcount>
 +      polylist.setVCountList(vcount_list);
-               
        // performs the actual writing
 -      prepareToAppendValues(is_triangulated, facelist, vcount_list);
 +      polylist.prepareToAppendValues();
-       
        // <p>
        int texindex = 0;
        for (i = 0; i < totpolys; i++) {
  
                texindex += loop_count;
        }
-               
 -      finishList(is_triangulated, facelist);
 -      delete facelist;
 +      polylist.finish();
  }
  
  // creates <source> for positions
@@@ -537,12 -777,18 +537,12 @@@ void GeometryExporter::createTexcoordsS
                int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, a);
                if (!this->export_settings->active_uv_only || layer_index == active_uv_index) {
                        MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
-                       
                        COLLADASW::FloatSourceF source(mSW);
 -                      std::string active_uv_name(bc_get_active_uvlayer_name(me));
 -                      std::string effective_id = geom_id; // (active_uv_name == "") ? geom_id : active_uv_name;
 -                      std::string layer_id = makeTexcoordSourceId(
 -                              effective_id,
 -                              a,
 -                              this->export_settings->active_uv_only );
 -
 +                      std::string layer_id = makeTexcoordSourceId(geom_id, a, this->export_settings->active_uv_only);
                        source.setId(layer_id);
                        source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
-                       
                        source.setAccessorCount(totuv);
                        source.setAccessorStride(2);
                        COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
@@@ -88,15 -85,33 +88,15 @@@ public
                                                     Mesh   *me,
                                                     std::string& geom_id);
  
 -      // Create polylists for meshes with Materials
 +      // powerful because it handles both cases when there is material and when there's not
        void createPolylist(short material_index,
 -              bool has_uvs,
 -              bool has_color,
 -              Object *ob,
 -              Mesh   *me,
 -              std::string& geom_id,
 -              std::vector<BCPolygonNormalsIndices>& norind);
 -
 -      // Create polylists for meshes with UV Textures
 -      void createPolylists(std::set<Image *> uv_images,
 -              bool has_uvs,
 -              bool has_color,
 -              Object *ob,
 -              Mesh   *me,
 -              std::string& geom_id,
 -              std::vector<BCPolygonNormalsIndices>& norind);
 -
 -      // Create polylists for meshes with UV Textures
 -      void createPolylist(std::string imageid,
 -              bool has_uvs,
 -              bool has_color,
 -              Object *ob,
 -              Mesh   *me,
 -              std::string& geom_id,
 -              std::vector<BCPolygonNormalsIndices>& norind);
 +                                              bool has_uvs,
 +                                              bool has_color,
 +                                              Object *ob,
 +                                              Mesh   *me,
 +                                              std::string& geom_id,
 +                                              std::vector<BCPolygonNormalsIndices>& norind);
-       
        // creates <source> for positions
        void createVertsSource(std::string geom_id, Mesh *me);
  
@@@ -53,11 -53,11 +53,11 @@@ ImagesExporter::ImagesExporter(COLLADAS
  {
  }
  
- void ImagesExporter::export_UV_Image(Image *image, bool use_copies) 
+ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
  {
 -      std::string id(id_name(image));
 -      std::string translated_id(translate_id(id));
 -      bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_id) == mImages.end();
 +      std::string name(id_name(image));
 +      std::string translated_name(translate_id(name));
 +      bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_name) == mImages.end();
  
        if (not_yet_exported) {
  
@@@ -41,16 -41,22 +41,16 @@@ extern "C" 
  #include "collada_internal.h"
  #include "collada_utils.h"
  
 -void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type)
 +void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only)
  {
 -      bool all_uv_layers = !active_uv_only;
 -      COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
 +      for (int a = 0; a < ob->totcol; a++) {
 +              Material *ma = give_current_material(ob, a + 1);
-                       
 -      if (export_texture_type == BC_TEXTURE_TYPE_UV)
 -      {
 -              std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
 -              std::set<Image *>::iterator uv_images_iter;
 -              for (uv_images_iter = uv_images.begin();
 -                   uv_images_iter != uv_images.end();
 -                   uv_images_iter++)
 -              {
 -                      Image *ima = *uv_images_iter;
 -                      std::string matid(id_name(ima));
 -                      matid = get_material_id_from_id(matid);
 +              COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
 +
 +              if (ma) {
 +                      std::string matid(get_material_id(ma));
 +                      matid = translate_id(matid);
                        std::ostringstream ostr;
                        ostr << matid;
                        COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
@@@ -58,9 -64,9 +58,9 @@@
                        // create <bind_vertex_input> for each uv map
                        Mesh *me = (Mesh *)ob->data;
                        int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
-                       
                        int map_index = 0;
 -                      int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
 +                      int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) -1;
                        for (int b = 0; b < totlayer; b++) {
                                if (!active_uv_only || b == active_uv_index) {
                                        char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
@@@ -164,6 -173,23 +164,6 @@@ bool LightsExporter::exportBlenderProfi
        cla.addExtraTechniqueParameter("blender", "area_size", la->area_size);
        cla.addExtraTechniqueParameter("blender", "area_sizey", la->area_sizey);
        cla.addExtraTechniqueParameter("blender", "area_sizez", la->area_sizez);
-       
 -      cla.addExtraTechniqueParameter("blender", "adapt_thresh", la->adapt_thresh);
 -      cla.addExtraTechniqueParameter("blender", "ray_samp_method", la->ray_samp_method);
 -      cla.addExtraTechniqueParameter("blender", "shadhalostep", la->shadhalostep);
 -      cla.addExtraTechniqueParameter("blender", "sun_effect_type", la->shadhalostep);
 -      cla.addExtraTechniqueParameter("blender", "skyblendtype", la->skyblendtype);
 -      cla.addExtraTechniqueParameter("blender", "horizon_brightness", la->horizon_brightness);
 -      cla.addExtraTechniqueParameter("blender", "spread", la->spread);
 -      cla.addExtraTechniqueParameter("blender", "sun_brightness", la->sun_brightness);
 -      cla.addExtraTechniqueParameter("blender", "sun_size", la->sun_size);
 -      cla.addExtraTechniqueParameter("blender", "backscattered_light", la->backscattered_light);
 -      cla.addExtraTechniqueParameter("blender", "sun_intensity", la->sun_intensity);
 -      cla.addExtraTechniqueParameter("blender", "atm_turbidity", la->atm_turbidity);
 -      cla.addExtraTechniqueParameter("blender", "atm_extinction_factor", la->atm_extinction_factor);
 -      cla.addExtraTechniqueParameter("blender", "atm_distance_factor", la->atm_distance_factor);
 -      cla.addExtraTechniqueParameter("blender", "skyblendfac", la->skyblendfac);
 -      cla.addExtraTechniqueParameter("blender", "sky_exposure", la->sky_exposure);
 -      cla.addExtraTechniqueParameter("blender", "sky_colorspace", la->sky_colorspace);
        return true;
  }
@@@ -207,11 -207,7 +207,11 @@@ void VCOLDataWrapper::get_vcol(int v_in
  
  }
  
 -MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce) : unitconverter(unitconv), scene(sce), armature_importer(arm) {
 +MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce, ViewLayer *view_layer):
-       unitconverter(unitconv), 
++      unitconverter(unitconv),
 +      scene(sce),
 +      view_layer(view_layer),
 +      armature_importer(arm) {
  }
  
  bool MeshImporter::set_poly_indices(MPoly *mpoly, MLoop *mloop, int loop_index, unsigned int *indices, int loop_count)
@@@ -1012,19 -1052,21 +1012,19 @@@ void MeshImporter::optimize_material_as
   * which materials shall be moved to the created geometries. Also see
   * optimize_material_assignements() above.
   */
 -MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
 -                                              std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
 -                                              Object *ob, const COLLADAFW::UniqueId *geom_uid,
 -                                              char *layername, MTFace *texture_face,
 -                                              std::map<Material *, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index)
 +void MeshImporter::assign_material_to_geom(
 +        COLLADAFW::MaterialBinding cmaterial,
 +        std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
 +        Object *ob, const COLLADAFW::UniqueId *geom_uid,
 +        short mat_index)
  {
 -      MTex *color_texture = NULL;
 -      Mesh *me = (Mesh *)ob->data;
        const COLLADAFW::UniqueId& ma_uid = cmaterial.getReferencedMaterial();
-       
        // do we know this material?
        if (uid_material_map.find(ma_uid) == uid_material_map.end()) {
-               
                fprintf(stderr, "Cannot find material by UID.\n");
 -              return NULL;
 +              return;
        }
  
        // first time we get geom_uid, ma_uid pair. Save for later check.
        // See note above.
        ob->actcol=0;
        assign_material(G.main, ob, ma, mat_index + 1, BKE_MAT_ASSIGN_OBJECT);
-       
 -      COLLADAFW::TextureCoordinateBindingArray& tex_array =
 -          cmaterial.getTextureCoordinateBindingArray();
 -      TexIndexTextureArrayMap texindex_texarray_map = material_texture_mapping_map[ma];
 -      unsigned int i;
 -      // loop through <bind_vertex_inputs>
 -      for (i = 0; i < tex_array.getCount(); i++) {
 -
 -              color_texture = assign_textures_to_uvlayer(tex_array[i], me, texindex_texarray_map,
 -                                                          color_texture);
 -      }
 -
 -      // set texture face
 -      if (color_texture &&
 -          strlen((color_texture)->uvname) &&
 -          !STREQ(layername, color_texture->uvname))
 -      {
 -              texture_face = (MTFace *)CustomData_get_layer_named(&me->fdata, CD_MTFACE,
 -                                                                  color_texture->uvname);
 -              strcpy(layername, color_texture->uvname);
 -      }
 -
        MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid];
        COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId();
-       
        // assign material indices to mesh faces
        if (mat_prim_map.find(mat_id) != mat_prim_map.end()) {
-               
                std::vector<Primitive>& prims = mat_prim_map[mat_id];
-               
                std::vector<Primitive>::iterator it;
-               
                for (it = prims.begin(); it != prims.end(); it++) {
                        Primitive& prim = *it;
                        MPoly *mpoly = prim.mpoly;
  
 -                      for (i = 0; i < prim.totpoly; i++, mpoly++) {
 +                      for (int i = 0; i < prim.totpoly; i++, mpoly++) {
                                mpoly->mat_nr = mat_index;
 -                              // bind texture images to faces
 -                              if (texture_face && color_texture) {
 -                                      texture_face->tpage = (Image *)color_texture->tex->ima;
 -                                      texture_face++;
 -                              }
                        }
                }
-       }       
+       }
 -      return texture_face;
  }
  
  Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
                                           bool isController,
 -                                         std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
 -                                         std::map<Material *, TexIndexTextureArrayMap>& material_texture_mapping_map)
 +                                         std::map<COLLADAFW::UniqueId, Material *>& uid_material_map)
  {
        const COLLADAFW::UniqueId *geom_uid = &geom->getInstanciatedObjectId();
-       
        // check if node instanciates controller or geometry
        if (isController) {
-               
                geom_uid = armature_importer->get_geometry_uid(*geom_uid);
-               
                if (!geom_uid) {
                        fprintf(stderr, "Couldn't find a mesh UID by controller's UID.\n");
                        return NULL;
        // name Object
        const std::string& id = node->getName().size() ? node->getName() : node->getOriginalId();
        const char *name = (id.length()) ? id.c_str() : NULL;
-       
        // add object
 -      Object *ob = bc_add_object(scene, OB_MESH, name);
 +      Object *ob = bc_add_object(scene, view_layer, OB_MESH, name);
        bc_set_mark(ob); // used later for material assignement optimization
  
  
        id_us_plus(&old_mesh->id);  /* Because BKE_mesh_assign_object would have already decreased it... */
        BKE_libblock_free_us(G.main, old_mesh);
  
 -      char layername[100];
 -      layername[0] = '\0';
 -      MTFace *texture_face = NULL;
 -
        COLLADAFW::MaterialBindingArray& mat_array =
            geom->getMaterialBindings();
-       
        // loop through geom's materials
        for (unsigned int i = 0; i < mat_array.getCount(); i++) {
-               
                if (mat_array[i].getReferencedMaterial().isValid()) {
 -                      texture_face = assign_material_to_geom(mat_array[i], uid_material_map, ob, geom_uid,
 -                                                             layername, texture_face,
 -                                                             material_texture_mapping_map, i);
 +                      assign_material_to_geom(
 +                              mat_array[i], uid_material_map, ob, geom_uid,
 +                              i);
                }
                else {
                        fprintf(stderr, "invalid referenced material for %s\n", mat_array[i].getName().c_str());
@@@ -165,19 -164,24 +165,19 @@@ public
        virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid);
  
        virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId& geom_uid);
-       
 -      MTex *assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture,
 -                                       Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map,
 -                                       MTex *color_texture);
 -
        void optimize_material_assignements();
  
 -      MTFace *assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
 -                                      std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
 -                                      Object *ob, const COLLADAFW::UniqueId *geom_uid,
 -                                      char *layername, MTFace *texture_face,
 -                                      std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index);
 +      void assign_material_to_geom(
 +              COLLADAFW::MaterialBinding cmaterial,
 +              std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
 +              Object *ob, const COLLADAFW::UniqueId *geom_uid,
 +              short mat_index);
-       
-       
        Object *create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
                                   bool isController,
 -                                 std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
 -                                 std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map);
 +                                 std::map<COLLADAFW::UniqueId, Material*>& uid_material_map);
  
        // create a mesh storing a pointer in a map so it can be retrieved later by geometry UID
        bool write_geometry(const COLLADAFW::Geometry* geom);
@@@ -49,8 -48,8 +49,8 @@@ void SceneExporter::exportScene(bContex
        closeLibrary();
  }
  
 -void SceneExporter::exportHierarchy(bContext *C, Scene *sce)
 +void SceneExporter::exportHierarchy(bContext *C, Depsgraph *depsgraph, Scene *sce)
- {     
+ {
        LinkNode *node;
        std::vector<Object *> base_objects;
  
@@@ -100,9 -100,9 +100,9 @@@ public
  
  private:
        friend class ArmatureExporter;
 -      void exportHierarchy(bContext *C, Scene *sce);
 -      void writeNodes(bContext *C, Object *ob, Scene *sce);
 +      void exportHierarchy(bContext *C, struct Depsgraph *depsgraph, Scene *sce);
 +      void writeNodes(bContext *C, struct Depsgraph *depsgraph, Object *ob, Scene *sce);
-       
        ArmatureExporter *arm_exporter;
        const ExportSettings *export_settings;
  };
Simple merge
Simple merge
@@@ -102,10 -102,10 +102,10 @@@ void BIK_execute_tree(struct Depsgraph 
        IKPlugin *plugin = get_plugin(ob->pose);
  
        if (plugin && plugin->execute_tree_func)
 -              plugin->execute_tree_func(scene, ob, pchan, ctime);
 +              plugin->execute_tree_func(depsgraph, scene, ob, pchan, ctime);
  }
  
- void BIK_release_tree(struct Scene *scene, Object *ob, float ctime) 
+ void BIK_release_tree(struct Scene *scene, Object *ob, float ctime)
  {
        IKPlugin *plugin = get_plugin(ob->pose);
  
@@@ -881,10 -877,10 +881,10 @@@ static int convert_channels(struct Deps
                ikchan->owner = ikscene->blArmature;
  
                // the constraint and channels must be applied before we build the iTaSC scene,
-               // this is because some of the pose data (e.g. pose head) don't have corresponding 
+               // this is because some of the pose data (e.g. pose head) don't have corresponding
                // joint angles and can't be applied to the iTaSC armature dynamically
                if (!(pchan->flag & POSE_DONE))
 -                      BKE_pose_where_is_bone(ikscene->blscene, ikscene->blArmature, pchan, ctime, 1);
 +                      BKE_pose_where_is_bone(depsgraph, ikscene->blscene, ikscene->blArmature, pchan, ctime, 1);
                // tell blender that this channel was controlled by IK, it's cleared on each BKE_pose_where_is()
                pchan->flag |= (POSE_DONE | POSE_CHAIN);
  
@@@ -306,8 -305,7 +306,8 @@@ static void node_composit_init_image(bN
        iuser->sfra = 1;
        iuser->fie_ima = 2;
        iuser->ok = 1;
-       
 +      iuser->flag |= IMA_ANIM_ALWAYS;
        /* setup initial outputs */
        cmp_node_image_verify_outputs(ntree, node, false);
  }
@@@ -80,10 -79,11 +80,10 @@@ static void shader_get_from_context(con
  {
        SpaceNode *snode = CTX_wm_space_node(C);
        Scene *scene = CTX_data_scene(C);
 -      Object *ob = OBACT;
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      Object *ob = OBACT(view_layer);
-       
 -      if ((snode->shaderfrom == SNODE_SHADER_OBJECT) ||
 -          (BKE_scene_use_new_shading_nodes(scene) == false))
 -      {
 +      if (snode->shaderfrom == SNODE_SHADER_OBJECT) {
                if (ob) {
                        *r_from = &ob->id;
                        if (ob->type == OB_LAMP) {
@@@ -175,13 -179,13 +175,13 @@@ bNodeTreeType *ntreeType_Shader
  void register_node_tree_type_sh(void)
  {
        bNodeTreeType *tt = ntreeType_Shader = MEM_callocN(sizeof(bNodeTreeType), "shader node tree type");
-       
        tt->type = NTREE_SHADER;
        strcpy(tt->idname, "ShaderNodeTree");
 -      strcpy(tt->ui_name, "Shader");
 +      strcpy(tt->ui_name, "Shader Editor");
        tt->ui_icon = 0;    /* defined in drawnode.c */
        strcpy(tt->ui_description, "Shader nodes");
-       
        tt->foreach_nodeclass = foreach_nodeclass;
        tt->localize = localize;
        tt->local_sync = local_sync;
@@@ -699,7 -601,19 +699,7 @@@ bool ntreeShaderExecTree(bNodeTree *ntr
        bNodeThreadStack *nts = NULL;
        bNodeTreeExec *exec = ntree->execdata;
        int compat;
-       
 -      /* convert caller data to struct */
 -      scd.shi = shi;
 -      scd.shr = shr;
 -
 -      /* each material node has own local shaderesult, with optional copying */
 -      memset(shr, 0, sizeof(ShadeResult));
 -
        /* ensure execdata is only initialized once */
        if (!exec) {
                BLI_thread_lock(LOCK_NODES);
  
                exec = ntree->execdata;
        }
-       
 -      nts = ntreeGetThreadStack(exec, shi->thread);
 -      compat = ntreeExecThreadNodes(exec, nts, &scd, shi->thread);
 +      nts = ntreeGetThreadStack(exec, thread);
 +      compat = ntreeExecThreadNodes(exec, nts, &scd, thread);
        ntreeReleaseThreadStack(nts);
-       
 -      // \note: set material back to preserved material
 -      shi->mat = mat;
 -
 -      /* better not allow negative for now */
 -      if (shr->combined[0] < 0.0f) shr->combined[0] = 0.0f;
 -      if (shr->combined[1] < 0.0f) shr->combined[1] = 0.0f;
 -      if (shr->combined[2] < 0.0f) shr->combined[2] = 0.0f;
 -
        /* if compat is zero, it has been using non-compatible nodes */
        return compat;
  }
@@@ -140,11 -189,11 +140,11 @@@ static void gpu_stack_from_data_list(GP
  {
        bNodeSocket *sock;
        int i;
-       
        for (sock = sockets->first, i = 0; sock; sock = sock->next, i++)
                node_gpu_stack_from_data(&gs[i], sock->type, ns[i]);
-       
 -      gs[i].type = GPU_NONE;
 +      gs[i].end = true;
  }
  
  static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
@@@ -44,15 -44,40 +44,15 @@@ static int node_shader_gpu_fresnel(GPUM
        if (!in[1].link) {
                in[1].link = GPU_builtin(GPU_VIEW_NORMAL);
        }
 -      else if (GPU_material_use_world_space_shading(mat)) {
 +      else {
                GPU_link(mat, "direction_transform_m4v3", in[1].link, GPU_builtin(GPU_VIEW_MATRIX), &in[1].link);
        }
-       
 -      return GPU_stack_link(mat, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_POSITION));
 +      return GPU_stack_link(mat, node, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_POSITION));
  }
  
 -static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
 +static void node_shader_exec_fresnel(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out))
  {
 -      ShadeInput *shi = ((ShaderCallData *)data)->shi;
 -
 -      /* Compute IOR. */
 -      float eta;
 -      nodestack_get_vec(&eta, SOCK_FLOAT, in[0]);
 -      eta = max_ff(eta, 0.00001);
 -      eta = shi->flippednor ? 1 / eta : eta;
 -
 -      /* Get normal from socket, but only if linked. */
 -      bNodeSocket *sock_normal = node->inputs.first;
 -      sock_normal = sock_normal->next;
 -
 -      float n[3];
 -      if (sock_normal->link) {
 -              nodestack_get_vec(n, SOCK_VECTOR, in[1]);
 -      }
 -      else {
 -              copy_v3_v3(n, shi->vn);
 -      }
 -
 -      if (shi->use_world_space_shading) {
 -              mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), n);
 -      }
 -
 -      out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, eta);
  }
  
  /* node type definition */
@@@ -48,18 -48,16 +48,18 @@@ static int node_shader_gpu_tex_coord(GP
        GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, "");
        GPUMatType type = GPU_Material_get_type(mat);
  
 -      if (type == GPU_MATERIAL_TYPE_MESH) {
 -              return GPU_stack_link(mat, "node_tex_coord", in, out,
 +      GPU_link(mat, "generated_from_orco", orco, &orco);
-       
++
 +      if (type == GPU_MATERIAL_TYPE_WORLD) {
 +              return GPU_stack_link(mat, node, "node_tex_coord_background", in, out,
                                      GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
                                      GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
                                      GPU_builtin(GPU_CAMERA_TEXCO_FACTORS), orco, mtface);
        }
        else {
 -              return GPU_stack_link(mat, "node_tex_coord_background", in, out,
 +              return GPU_stack_link(mat, node, "node_tex_coord", in, out,
                                      GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
-                                     GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), 
+                                     GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
                                      GPU_builtin(GPU_CAMERA_TEXCO_FACTORS), orco, mtface);
        }
  }
@@@ -76,10 -76,10 +76,10 @@@ static int node_shader_gpu_tex_environm
        node_shader_gpu_tex_mapping(mat, node, in, out);
  
        if (tex->projection == SHD_PROJ_EQUIRECTANGULAR)
 -              GPU_stack_link(mat, "node_tex_environment_equirectangular", in, out, GPU_image(ima, iuser, isdata));
 +              GPU_stack_link(mat, node, "node_tex_environment_equirectangular", in, out, GPU_image(ima, iuser, isdata));
        else
 -              GPU_stack_link(mat, "node_tex_environment_mirror_ball", in, out, GPU_image(ima, iuser, isdata));
 +              GPU_stack_link(mat, node, "node_tex_environment_mirror_ball", in, out, GPU_image(ima, iuser, isdata));
-               
        ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
        if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
            GPU_material_do_color_management(mat))
@@@ -64,13 -62,37 +64,13 @@@ static void texture_get_from_context
  {
        SpaceNode *snode = CTX_wm_space_node(C);
        Scene *scene = CTX_data_scene(C);
 -      Object *ob = OBACT;
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
 +      Object *ob = OBACT(view_layer);
        Tex *tx = NULL;
  
 -      if (snode->texfrom == SNODE_TEX_OBJECT) {
 -              if (ob) {
 -                      tx = give_current_object_texture(ob);
 -                      if (tx) {
 -                              if (ob->type == OB_LAMP)
 -                                      *r_from = (ID *)ob->data;
 -                              else
 -                                      *r_from = (ID *)give_current_material(ob, ob->actcol);
 -
 -                              /* from is not set fully for material nodes, should be ID + Node then */
 -                              *r_id = &tx->id;
 -                              *r_ntree = tx->nodetree;
 -                      }
 -              }
 -      }
 -      else if (snode->texfrom == SNODE_TEX_WORLD) {
 -              if (scene->world) {
 -                      *r_from = (ID *)scene->world;
 -                      tx = give_current_world_texture(scene->world);
 -                      if (tx) {
 -                              *r_id = &tx->id;
 -                              *r_ntree = tx->nodetree;
 -                      }
 -              }
 -      }
 -      else if (snode->texfrom == SNODE_TEX_BRUSH) {
 +      if (snode->texfrom == SNODE_TEX_BRUSH) {
                struct Brush *brush = NULL;
-               
                if (ob && (ob->mode & OB_MODE_SCULPT))
                        brush = BKE_paint_brush(&scene->toolsettings->sculpt->paint);
                else
@@@ -161,13 -183,13 +161,13 @@@ bNodeTreeType *ntreeType_Texture
  void register_node_tree_type_tex(void)
  {
        bNodeTreeType *tt = ntreeType_Texture = MEM_callocN(sizeof(bNodeTreeType), "texture node tree type");
-       
        tt->type = NTREE_TEXTURE;
        strcpy(tt->idname, "TextureNodeTree");
 -      strcpy(tt->ui_name, "Texture");
 +      strcpy(tt->ui_name, "Texture Editor");
        tt->ui_icon = 0;    /* defined in drawnode.c */
        strcpy(tt->ui_description, "Texture nodes");
-       
        tt->foreach_nodeclass = foreach_nodeclass;
        tt->update = update;
        tt->localize = localize;
@@@ -318,7 -341,8 +318,7 @@@ int ntreeTexExecTree
        data.which_output = which_output;
        data.cfra = cfra;
        data.mtex = mtex;
-       
 -      data.shi = shi;
        /* ensure execdata is only initialized once */
        if (!exec) {
                BLI_thread_lock(LOCK_NODES);
@@@ -67,13 -67,13 +67,13 @@@ static void do_proc(float *result, TexP
        }
        else
                texres.nor = NULL;
-       
        textype = multitex_nodes(tex, p->co, p->dxt, p->dyt, p->osatex,
 -                               &texres, thread, 0, p->shi, p->mtex, NULL);
 +                               &texres, thread, 0, p->mtex, NULL);
-       
        if (is_normal)
                return;
-       
        if (textype & TEX_RGB) {
                copy_v4_v4(result, &texres.tr);
        }
@@@ -72,14 -72,14 +72,14 @@@ static void colorfn(float *out, TexPara
                int textype;
                float nor[] = {0, 0, 0};
                float col1[4], col2[4];
-               
                tex_input_rgba(col1, in[0], p, thread);
                tex_input_rgba(col2, in[1], p, thread);
-               
                texres.nor = nor;
                textype = multitex_nodes(nodetex, co, dxt, dyt, p->osatex,
 -                                       &texres, thread, 0, p->shi, p->mtex, NULL);
 +                                       &texres, thread, 0, p->mtex, NULL);
-               
                if (textype & TEX_RGB) {
                        copy_v4_v4(out, &texres.tr);
                }
@@@ -1088,6 -1088,27 +1088,6 @@@ int BPH_cloth_solve(Object *ob, float f
                BPH_mass_spring_get_motion_state(id, i, verts[i].x, verts[i].v);
                copy_v3_v3(verts[i].txold, verts[i].x);
        }
-       
        return 1;
  }
 -
 -bool BPH_cloth_solver_get_texture_data(Object *UNUSED(ob), ClothModifierData *clmd, VoxelData *vd)
 -{
 -      Cloth *cloth = clmd->clothObject;
 -      HairGrid *grid;
 -      float gmin[3], gmax[3];
 -
 -      if (!clmd->clothObject || !clmd->clothObject->implicit)
 -              return false;
 -
 -      hair_get_boundbox(clmd, gmin, gmax);
 -
 -      grid = BPH_hair_volume_create_vertex_grid(clmd->sim_parms->voxel_cell_size, gmin, gmax);
 -      cloth_continuum_fill_grid(grid, cloth);
 -
 -      BPH_hair_volume_get_texture_data(grid, vd);
 -
 -      BPH_hair_volume_free_vertex_grid(grid);
 -
 -      return true;
 -}
Simple merge
@@@ -103,11 -102,15 +103,11 @@@ typedef struct RenderPass 
  /* after render, the Combined pass is in combined, for renderlayers read from files it is a real pass */
  typedef struct RenderLayer {
        struct RenderLayer *next, *prev;
-       
        /* copy of RenderData */
        char name[RE_MAXNAME];
 -      unsigned int lay, lay_zmask, lay_exclude;
        int layflag, passflag, pass_xor;
-       
 -      struct Material *mat_override;
 -      struct Group *light_override;
 -
        /* MULTIVIEW_TODO: acolrect and scolrect are not supported by multiview at the moment.
         * If they are really required they should be in RenderView instead */
  
  
  
  #ifndef __INITRENDER_H__
- #define __INITRENDER_H__ 
+ #define __INITRENDER_H__
  
 -
  /* Functions */
  
 -void free_sample_tables(Render *re);
 -void make_sample_tables(Render *re);
 -
 -void RE_parts_init(Render *re, bool do_crop);
 +void RE_parts_init(Render *re);
  void RE_parts_free(Render *re);
  void RE_parts_clamp(Render *re);
  
@@@ -52,10 -91,20 +52,10 @@@ struct Main
  /* this is handed over to threaded hiding/passes/shading engine */
  typedef struct RenderPart {
        struct RenderPart *next, *prev;
-       
        RenderResult *result;                   /* result of part rendering */
        ListBase fullresult;                    /* optional full sample buffers */
-       
 -      int *recto;                                             /* object table for objects */
 -      int *rectp;                                             /* polygon index table */
 -      int *rectz;                                             /* zbuffer */
 -      int *rectmask;                                  /* negative zmask */
 -      intptr_t *rectdaps;                                     /* delta acum buffer for pixel structs */
 -      int *rectbacko;                                 /* object table for backside sss */
 -      int *rectbackp;                                 /* polygon index table for backside sss */
 -      int *rectbackz;                                 /* zbuffer for backside sss */
 -      intptr_t *rectall;                                      /* buffer for all faces for sss */
 -
        rcti disprect;                                  /* part coordinates within total picture */
        int rectx, recty;                               /* the size */
        int nr;                                                 /* nr is partnr */
@@@ -74,10 -127,13 +74,10 @@@ struct Render 
        struct Render *next, *prev;
        char name[RE_MAXNAME];
        int slot;
-       
        /* state settings */
 -      short flag, osa, ok, result_ok;
 -
 -      /* due to performance issues, getting initialized from color management settings once on Render initialization */
 -      bool scene_color_manage;
 +      short flag, ok, result_ok;
-       
        /* result of rendering */
        RenderResult *result;
        /* if render with single-layer option, other rendered layers are stored here */
                                                         * without border & crop. convert to long before multiplying together to avoid overflow. */
        rcti disprect;                  /* part within winx winy */
        rctf viewplane;                 /* mapped on winx winy */
-       
 -      float viewdx, viewdy;   /* size of 1 pixel */
 -      float clipcrop;                 /* 2 pixel boundary to prevent clip when filter used */
        /* final picture width and height (within disprect) */
        int rectx, recty;
-       
-       /* real maximum size of parts after correction for minimum 
+       /* real maximum size of parts after correction for minimum
         * partx*xparts can be larger than rectx, in that case last part is smaller */
        int partx, party;
-       
 -      /* values for viewing */
 -      float ycor; /* (scene->xasp / scene->yasp), multiplied with 'winy' */
 -
 -      float panophi, panosi, panoco, panodxp, panodxv;
 -
 -      /* Matrices */
 -      float grvec[3];                 /* for world */
 -      float imat[3][3];               /* copy of viewinv */
 +      /* Camera transform, only used by Freestyle. */
        float viewmat[4][4], viewinv[4][4];
        float viewmat_orig[4][4];       /* for incremental render */
        float winmat[4][4];
        /* clippping */
        float clipsta;
        float clipend;
-       
 -      /* samples */
 -      SampleTables *samples;
 -      float jit[32][2];
 -      float mblur_jit[32][2];
 -      ListBase *qmcsamplers;
 -      int num_qmc_samplers;
 -
 -      /* shadow counter, detect shadow-reuse for shaders */
 -      int shadowsamplenr[BLENDER_MAX_THREADS];
 -
        /* main, scene, and its full copy of renderdata and world */
        struct Main *main;
        Scene *scene;
        RenderData r;
 -      World wrld;
 +      ListBase view_layers;
 +      int active_view_layer;
        struct Object *camera_override;
        unsigned int lay, layer_override;
-       
        ThreadRWMutex partsmutex;
        ListBase parts;
-       
        /* render engine */
        struct RenderEngine *engine;
-       
 -      /* octree tables and variables for raytrace */
 -      struct RayObject *raytree;
 -      struct RayFace *rayfaces;
 -      struct VlakPrimitive *rayprimitives;
 -      float maxdist; /* needed for keeping an incorrect behavior of SUN and HEMI lights (avoid breaking old scenes) */
 -
 -      /* occlusion tree */
 -      void *occlusiontree;
 -      ListBase strandsurface;
 -
 -      /* use this instead of R.r.cfra */
 -      float mblur_offs, field_offs;
 -
 -      /* render database */
 -      int totvlak, totvert, tothalo, totstrand, totlamp;
 -      struct HaloRen **sortedhalos;
 -
 -      ListBase lights;        /* GroupObject pointers */
 -      ListBase lampren;       /* storage, for free */
 -
 -      ListBase objecttable;
 -
 -      struct ObjectInstanceRen *objectinstance;
 -      ListBase instancetable;
 -      int totinstance;
 -
 -      struct Image *bakebuf;
 -
 -      struct GHash *orco_hash;
 -
 -      struct GHash *sss_hash;
 -      ListBase *sss_points;
 -      struct Material *sss_mat;
 -
 -      ListBase customdata_names;
 -
 -      struct Object *excludeob;
 -      ListBase render_volumes_inside;
 -      ListBase volumes;
 -
  #ifdef WITH_FREESTYLE
        struct Main *freestyle_bmain;
        ListBase freestyle_renders;
@@@ -112,11 -114,11 +112,11 @@@ void RE_engines_register(RenderEngineTy
  RenderEngineType *RE_engines_find(const char *idname)
  {
        RenderEngineType *type;
-       
        type = BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
        if (!type)
 -              type = &internal_render_type;
 +              type = BLI_findstring(&R_engines, "BLENDER_EEVEE", offsetof(RenderEngineType, idname));
-       
        return type;
  }
  
@@@ -205,7 -210,12 +205,7 @@@ int imagewrap(Tex *tex, Image *ima, ImB
                        if (y<0) y+= ibuf->y;
                }
        }
-       
 -      /* warning, no return before setting back! */
 -      if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
 -              ibuf->rect+= (ibuf->x*ibuf->y);
 -      }
 -
        /* keep this before interpolation [#29761] */
        if (ima) {
                if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
        else { /* no filtering */
                ibuf_get_color(&texres->tr, ibuf, x, y);
        }
-       
 -      if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
 -              ibuf->rect-= (ibuf->x*ibuf->y);
 -      }
 -
        if (texres->nor) {
                if (tex->imaflag & TEX_NORMALMAP) {
                        /* qdn: normal from color
@@@ -1281,7 -1310,10 +1281,7 @@@ static int imagewraposa_aniso(Tex *tex
        else
                texres->tin = texres->ta;
        if (tex->flag & TEX_NEGALPHA) texres->ta = 1.f - texres->ta;
-       
 -      if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields))
 -              ibuf->rect -= ibuf->x*ibuf->y;
 -
        if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {    /* normal from color */
                /* The invert of the red channel is to make
                 * the normal map compliant with the outside world.
@@@ -1378,7 -1410,19 +1378,7 @@@ int imagewraposa(Tex *tex, Image *ima, 
                fx= texvec[0];
                fy= texvec[1];
        }
-       
 -      if (ibuf->flags & IB_fields) {
 -              if (R.r.mode & R_FIELDS) {                      /* field render */
 -                      if (R.flag & R_SEC_FIELD) {             /* correction for 2nd field */
 -                              /* fac1= 0.5/( (float)ibuf->y ); */
 -                              /* fy-= fac1; */
 -                      }
 -                      else {                          /* first field */
 -                              fy+= 0.5f/( (float)ibuf->y );
 -                      }
 -              }
 -      }
 -
        /* pixel coordinates */
  
        minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
        }
  
        if (tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
-       
 -      if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
 -              ibuf->rect-= (ibuf->x*ibuf->y);
 -      }
 -
        if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {
                /* qdn: normal from color
                 * The invert of the red channel is to make
@@@ -1718,11 -1771,17 +1718,11 @@@ void image_sample(Image *ima, float fx
                zero_v4(result);
                return;
        }
-       
 -      if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) )
 -              ibuf->rect+= (ibuf->x*ibuf->y);
 -
        texres.talpha = true; /* boxsample expects to be initialized */
        boxsample(ibuf, fx, fy, fx + dx, fy + dy, &texres, 0, 1);
        copy_v4_v4(result, &texres.tr);
-       
 -      if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) )
 -              ibuf->rect-= (ibuf->x*ibuf->y);
 -
        ima->flag|= IMA_USED_FOR_RENDER;
  
        BKE_image_pool_release_ibuf(ima, ibuf, pool);
@@@ -242,7 -564,11 +242,7 @@@ void RE_parts_init(Render *re
        /* part count */
        xparts = (re->rectx + partx - 1) / partx;
        yparts = (re->recty + party - 1) / party;
-       
 -      /* calculate rotation factor of 1 pixel */
 -      if (re->r.mode & R_PANORAMA)
 -              re->panophi = panorama_pixel_rot(re);
 -
        for (nr = 0; nr < xparts * yparts; nr++) {
                rcti disprect;
                int rectx, recty;
                /* so, now can we add this part? */
                if (rectx > 0 && recty > 0) {
                        RenderPart *pa = MEM_callocN(sizeof(RenderPart), "new part");
-                       
 -                      /* Non-box filters need 2 pixels extra to work */
 -                      if (do_crop && (re->r.filtertype || (re->r.mode & R_EDGE))) {
 -                              pa->crop = 2;
 -                              disprect.xmin -= pa->crop;
 -                              disprect.ymin -= pa->crop;
 -                              disprect.xmax += pa->crop;
 -                              disprect.ymax += pa->crop;
 -                              rectx += 2 * pa->crop;
 -                              recty += 2 * pa->crop;
 -                      }
                        pa->disprect = disprect;
                        pa->rectx = rectx;
                        pa->recty = recty;
  /* here we store all renders */
  static struct {
        ListBase renderlist;
- } RenderGlobal = {{NULL, NULL}}; 
+ } RenderGlobal = {{NULL, NULL}};
  
 -/* hardcopy of current render, used while rendering for speed */
 -Render R;
 -
  /* ********* alloc and free ******** */
  
  static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const int totvideos, const char *name_override);
@@@ -501,10 -517,14 +501,10 @@@ Render *RE_NewRender(const char *name
                BLI_strncpy(re->name, name, RE_MAXNAME);
                BLI_rw_mutex_init(&re->resultmutex);
                BLI_rw_mutex_init(&re->partsmutex);
 -              re->eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER);
        }
-       
        RE_InitRenderCB(re);
  
 -      /* init some variables */
 -      re->ycor = 1.0f;
 -
        return re;
  }
  
@@@ -574,11 -594,15 +574,11 @@@ void RE_FreeRender(Render *re
        /* main dbase can already be invalid now, some database-free code checks it */
        re->main = NULL;
        re->scene = NULL;
-       
 -      RE_Database_Free(re);   /* view render can still have full database */
 -      free_sample_tables(re);
 -
        render_result_free(re->result);
        render_result_free(re->pushedresult);
-       
        BLI_remlink(&RenderGlobal.renderlist, re);
 -      MEM_freeN(re->eval_ctx);
        MEM_freeN(re);
  }
  
@@@ -753,15 -785,35 +753,15 @@@ void RE_InitState(Render *re, Render *s
        }
  
        re->r.scemode = check_mode_full_sample(&re->r);
-       
 -      /* fullsample wants uniform osa levels */
 -      if (source && (re->r.scemode & R_FULL_SAMPLE)) {
 -              /* but, if source has no full sample we disable it */
 -              if ((source->r.scemode & R_FULL_SAMPLE) == 0)
 -                      re->r.scemode &= ~R_FULL_SAMPLE;
 -              else
 -                      re->r.osa = re->osa = source->osa;
 -      }
 -      else {
 -              /* check state variables, osa? */
 -              if (re->r.mode & (R_OSA)) {
 -                      re->osa = re->r.osa;
 -                      if (re->osa > 16) re->osa = 16;
 -              }
 -              else re->osa = 0;
 -      }
 -
 -      if (srl) {
 -              int index = BLI_findindex(&rd->layers, srl);
 +      if (single_layer) {
 +              int index = BLI_findindex(render_layers, single_layer);
                if (index != -1) {
 -                      re->r.actlay = index;
 +                      re->active_view_layer = index;
                        re->r.scemode |= R_SINGLE_LAYER;
                }
        }
-               
 -      /* always call, checks for gamma, gamma tables and jitter too */
 -      make_sample_tables(re);
 -
        /* if preview render, we try to keep old result */
        BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
  
        RE_parts_clamp(re);
  
        BLI_rw_mutex_unlock(&re->resultmutex);
-       
 -      re->mblur_offs = re->field_offs = 0.f;
 -
        RE_init_threadcount(re);
 +
 +      RE_point_density_fix_linking();
  }
  
  /* This function is only called by view3d rendering, which doesn't support
@@@ -1004,49 -1058,813 +1004,49 @@@ void RE_stats_draw_cb(Render *re, void 
  }
  void RE_progress_cb(Render *re, void *handle, void (*f)(void *handle, float))
  {
 -      re->progress = f;
 -      re->prh = handle;
 -}
 -
 -void RE_draw_lock_cb(Render *re, void *handle, void (*f)(void *handle, int i))
 -{
 -      re->draw_lock = f;
 -      re->dlh = handle;
 -}
 -
 -void RE_test_break_cb(Render *re, void *handle, int (*f)(void *handle))
 -{
 -      re->test_break = f;
 -      re->tbh = handle;
 -}
 -
 -
 -/* ********* add object data (later) ******** */
 -
 -/* object is considered fully prepared on correct time etc */
 -/* includes lights */
 -#if 0
 -void RE_AddObject(Render *UNUSED(re), Object *UNUSED(ob))
 -{
 -
 -}
 -#endif
 -
 -/* *************************************** */
 -
 -static int render_display_update_enabled(Render *re)
 -{
 -      /* don't show preprocess for previewrender sss */
 -      if (re->sss_points)
 -              return !(re->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW));
 -      else
 -              return 1;
 -}
 -
 -/* the main thread call, renders an entire part */
 -static void *do_part_thread(void *pa_v)
 -{
 -      RenderPart *pa = pa_v;
 -
 -      pa->status = PART_STATUS_IN_PROGRESS;
 -
 -      /* need to return nicely all parts on esc */
 -      if (R.test_break(R.tbh) == 0) {
 -
 -              if (!R.sss_points && (R.r.scemode & R_FULL_SAMPLE))
 -                      pa->result = render_result_new_full_sample(&R, &pa->fullresult, &pa->disprect, pa->crop, RR_USE_MEM, R.viewname);
 -              else
 -                      pa->result = render_result_new(&R, &pa->disprect, pa->crop, RR_USE_MEM, RR_ALL_LAYERS, R.viewname);
 -
 -              /* Copy EXR tile settings, so pipeline knows whether this is a result
 -               * for Save Buffers enabled rendering.
 -               *
 -               * TODO(sergey): This actually duplicates logic with external engine, so
 -               * worth looking into more generic solution.
 -               */
 -              pa->result->do_exr_tile = R.result->do_exr_tile;
 -
 -              if (R.sss_points)
 -                      zbufshade_sss_tile(pa);
 -              else if (R.osa)
 -                      zbufshadeDA_tile(pa);
 -              else
 -                      zbufshade_tile(pa);
 -
 -              /* we do actually write pixels, but don't allocate/deallocate anything,
 -               * so it is safe with other threads reading at the same time */
 -              BLI_rw_mutex_lock(&R.resultmutex, THREAD_LOCK_READ);
 -
 -              /* merge too on break! */
 -              if (R.result->do_exr_tile) {
 -                      render_result_exr_file_merge(R.result, pa->result, R.viewname);
 -              }
 -              else if (render_display_update_enabled(&R)) {
 -                      /* on break, don't merge in result for preview renders, looks nicer */
 -                      if (R.test_break(R.tbh) && (R.r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))) {
 -                              /* pass */
 -                      }
 -                      else {
 -                              render_result_merge(R.result, pa->result);
 -                      }
 -              }
 -
 -              BLI_rw_mutex_unlock(&R.resultmutex);
 -      }
 -
 -      pa->status = PART_STATUS_MERGED;
 -
 -      return NULL;
 -}
 -
 -/* calculus for how much 1 pixel rendered should rotate the 3d geometry */
 -/* is not that simple, needs to be corrected for errors of larger viewplane sizes */
 -/* called in initrender.c, RE_parts_init() and convertblender.c, for speedvectors */
 -float panorama_pixel_rot(Render *re)
 -{
 -      float psize, phi, xfac;
 -      float borderfac = (float)BLI_rcti_size_x(&re->disprect) / (float)re->winx;
 -      int xparts = (re->rectx + re->partx - 1) / re->partx;
 -
 -      /* size of 1 pixel mapped to viewplane coords */
 -      psize = BLI_rctf_size_x(&re->viewplane) / (float)re->winx;
 -      /* angle of a pixel */
 -      phi = atan(psize / re->clipsta);
 -
 -      /* correction factor for viewplane shifting, first calculate how much the viewplane angle is */
 -      xfac = borderfac * BLI_rctf_size_x(&re->viewplane) / (float)xparts;
 -      xfac = atan(0.5f * xfac / re->clipsta);
 -      /* and how much the same viewplane angle is wrapped */
 -      psize = 0.5f * phi * ((float)re->partx);
 -
 -      /* the ratio applied to final per-pixel angle */
 -      phi *= xfac / psize;
 -
 -      return phi;
 -}
 -
 -/* for panorama, we render per Y slice, and update
 - * camera parameters when we go the next slice */
 -static bool find_next_pano_slice(Render *re, int *slice, int *minx, rctf *viewplane)
 -{
 -      RenderPart *pa, *best = NULL;
 -      bool found = false;
 -
 -      *minx = re->winx;
 -
 -      if (!(re->r.mode & R_PANORAMA)) {
 -              /* for regular render, just one 'slice' */
 -              found = (*slice == 0);
 -              (*slice)++;
 -              return found;
 -      }
 -
 -      /* most left part of the non-rendering parts */
 -      for (pa = re->parts.first; pa; pa = pa->next) {
 -              if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
 -                      if (pa->disprect.xmin < *minx) {
 -                              found = true;
 -                              best = pa;
 -                              *minx = pa->disprect.xmin;
 -                      }
 -              }
 -      }
 -
 -      if (best) {
 -              float phi = panorama_pixel_rot(re);
 -
 -              R.panodxp = (re->winx - (best->disprect.xmin + best->disprect.xmax) ) / 2;
 -              R.panodxv = (BLI_rctf_size_x(viewplane) * R.panodxp) / (float)(re->winx);
 -
 -              /* shift viewplane */
 -              R.viewplane.xmin = viewplane->xmin + R.panodxv;
 -              R.viewplane.xmax = viewplane->xmax + R.panodxv;
 -              RE_SetWindow(re, &R.viewplane, R.clipsta, R.clipend);
 -              copy_m4_m4(R.winmat, re->winmat);
 -
 -              /* rotate database according to part coordinates */
 -              project_renderdata(re, projectverto, 1, -R.panodxp * phi, 1);
 -              R.panosi = sinf(R.panodxp * phi);
 -              R.panoco = cosf(R.panodxp * phi);
 -      }
 -
 -      (*slice)++;
 -
 -      return found;
 -}
 -
 -typedef struct SortRenderPart {
 -      RenderPart *pa;
 -      long long int dist;
 -} SortRenderPart;
 -
 -static int sort_render_part(const void *pa1, const void *pa2) {
 -      const SortRenderPart *rpa1 = pa1;
 -      const SortRenderPart *rpa2 = pa2;
 -
 -      if (rpa1->dist > rpa2->dist) return 1;
 -      else if (rpa1->dist < rpa2->dist) return -1;
 -
 -      return 0;
 -}
 -
 -static int sort_and_queue_parts(Render *re, int minx, ThreadQueue *workqueue)
 -{
 -      RenderPart *pa;
 -
 -      /* long long int's needed because of overflow [#24414] */
 -      long long int centx = re->winx / 2, centy = re->winy / 2, tot = 1;
 -      int totsort = 0;
 -
 -      /* find center of rendered parts, image center counts for 1 too */
 -      for (pa = re->parts.first; pa; pa = pa->next) {
 -              if (pa->status >= PART_STATUS_RENDERED) {
 -                      centx += BLI_rcti_cent_x(&pa->disprect);
 -                      centy += BLI_rcti_cent_y(&pa->disprect);
 -                      tot++;
 -              }
 -              else if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
 -                      if (!(re->r.mode & R_PANORAMA) || pa->disprect.xmin == minx) {
 -                              totsort++;
 -                      }
 -              }
 -      }
 -      centx /= tot;
 -      centy /= tot;
 -
 -      if (totsort > 0) {
 -              SortRenderPart *sortlist = MEM_mallocN(sizeof(*sortlist) * totsort, "renderpartsort");
 -              long int i = 0;
 -
 -              /* prepare the list */
 -              for (pa = re->parts.first; pa; pa = pa->next) {
 -                      if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
 -                              if (!(re->r.mode & R_PANORAMA) || pa->disprect.xmin == minx) {
 -                                      long long int distx = centx - BLI_rcti_cent_x(&pa->disprect);
 -                                      long long int disty = centy - BLI_rcti_cent_y(&pa->disprect);
 -                                      sortlist[i].dist = (long long int)sqrt(distx * distx + disty * disty);
 -                                      sortlist[i].pa = pa;
 -                                      i++;
 -                              }
 -                      }
 -              }
 -
 -              /* Now sort it */
 -              qsort(sortlist, totsort, sizeof(*sortlist), sort_render_part);
 -
 -              /* Finally flush it to the workqueue */
 -              for (i = 0; i < totsort; i++) {
 -                      pa = sortlist[i].pa;
 -                      pa->nr = i + 1; /* for nicest part, and for stats */
 -                      BLI_thread_queue_push(workqueue, pa);
 -              }
 -
 -              MEM_freeN(sortlist);
 -
 -              return totsort;
 -      }
 -
 -      return 0;
 -}
 -
 -static void print_part_stats(Render *re, RenderPart *pa)
 -{
 -      char str[64];
 -
 -      BLI_snprintf(str, sizeof(str), IFACE_("%s, Part %d-%d"), re->scene->id.name + 2, pa->nr, re->i.totpart);
 -      re->i.infostr = str;
 -      re->stats_draw(re->sdh, &re->i);
 -      re->i.infostr = NULL;
 -}
 -
 -typedef struct RenderThread {
 -      ThreadQueue *workqueue;
 -      ThreadQueue *donequeue;
 -
 -      int number;
 -
 -      void (*display_update)(void *handle, RenderResult *rr, volatile rcti *rect);
 -      void *duh;
 -} RenderThread;
 -
 -static void *do_render_thread(void *thread_v)
 -{
 -      RenderThread *thread = thread_v;
 -      RenderPart *pa;
 -
 -      while ((pa = BLI_thread_queue_pop(thread->workqueue))) {
 -              pa->thread = thread->number;
 -              do_part_thread(pa);
 -
 -              if (thread->display_update) {
 -                      thread->display_update(thread->duh, pa->result, NULL);
 -              }
 -
 -              BLI_thread_queue_push(thread->donequeue, pa);
 -
 -              if (R.test_break(R.tbh))
 -                      break;
 -      }
 -
 -      return NULL;
 -}
 -
 -static void main_render_result_end(Render *re)
 -{
 -      if (re->result->do_exr_tile) {
 -              BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
 -              render_result_exr_file_end(re);
 -              BLI_rw_mutex_unlock(&re->resultmutex);
 -      }
 -
 -      if (re->r.scemode & R_EXR_CACHE_FILE) {
 -              BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
 -              render_result_exr_file_cache_write(re);
 -              BLI_rw_mutex_unlock(&re->resultmutex);
 -      }
 -}
 -
 -static void main_render_result_new(Render *re)
 -{
 -      BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
 -
 -      /* first step; free the entire render result, make new, and/or prepare exr buffer saving */
 -      if (re->result == NULL || !(re->r.scemode & (R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))) {
 -              render_result_free(re->result);
 -
 -              if (re->sss_points && render_display_update_enabled(re))
 -                      re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
 -              else if (re->r.scemode & R_FULL_SAMPLE)
 -                      re->result = render_result_new_full_sample(re, &re->fullresult, &re->disprect, 0, RR_USE_EXR, RR_ALL_VIEWS);
 -              else
 -                      re->result = render_result_new(re, &re->disprect, 0,
 -                              (re->r.scemode & R_EXR_TILE_FILE) ? RR_USE_EXR : RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
 -      }
 -
 -      BLI_rw_mutex_unlock(&re->resultmutex);
 -
 -      if (re->result) {
 -              if (re->result->do_exr_tile) {
 -                      render_result_exr_file_begin(re);
 -              }
 -      }
 -}
 -
 -static void threaded_tile_processor(Render *re)
 -{
 -      RenderThread thread[BLENDER_MAX_THREADS];
 -      ThreadQueue *workqueue, *donequeue;
 -      ListBase threads;
 -      RenderPart *pa;
 -      rctf viewplane = re->viewplane;
 -      double lastdraw, elapsed, redrawtime = 1.0f;
 -      int totpart = 0, minx = 0, slice = 0, a, wait;
 -
 -      if (re->result == NULL)
 -              return;
 -
 -      /* warning; no return here without closing exr file */
 -      RE_parts_init(re, true);
 -
 -      /* assuming no new data gets added to dbase... */
 -      R = *re;
 -
 -      /* set threadsafe break */
 -      R.test_break = thread_break;
 -
 -      /* create and fill work queue */
 -      workqueue = BLI_thread_queue_init();
 -      donequeue = BLI_thread_queue_init();
 -
 -      /* for panorama we loop over slices */
 -      while (find_next_pano_slice(re, &slice, &minx, &viewplane)) {
 -              /* gather parts into queue */
 -              totpart = sort_and_queue_parts(re, minx, workqueue);
 -
 -              BLI_thread_queue_nowait(workqueue);
 -
 -              /* start all threads */
 -              BLI_threadpool_init(&threads, do_render_thread, re->r.threads);
 -
 -              for (a = 0; a < re->r.threads; a++) {
 -                      thread[a].workqueue = workqueue;
 -                      thread[a].donequeue = donequeue;
 -                      thread[a].number = a;
 -
 -                      if (render_display_update_enabled(re)) {
 -                              thread[a].display_update = re->display_update;
 -                              thread[a].duh = re->duh;
 -                      }
 -                      else {
 -                              thread[a].display_update = NULL;
 -                              thread[a].duh = NULL;
 -                      }
 -
 -                      BLI_threadpool_insert(&threads, &thread[a]);
 -              }
 -
 -              /* wait for results to come back */
 -              lastdraw = PIL_check_seconds_timer();
 -
 -              while (1) {
 -                      elapsed = PIL_check_seconds_timer() - lastdraw;
 -                      wait = (redrawtime - elapsed)*1000;
 -
 -                      /* handle finished part */
 -                      if ((pa=BLI_thread_queue_pop_timeout(donequeue, wait))) {
 -                              if (pa->result) {
 -                                      print_part_stats(re, pa);
 -
 -                                      render_result_free_list(&pa->fullresult, pa->result);
 -                                      pa->result = NULL;
 -                                      re->i.partsdone++;
 -                                      re->progress(re->prh, re->i.partsdone / (float)re->i.totpart);
 -                              }
 -
 -                              totpart--;
 -                      }
 -
 -                      /* check for render cancel */
 -                      if ((g_break=re->test_break(re->tbh)))
 -                              break;
 -
 -                      /* or done with parts */
 -                      if (totpart == 0)
 -                              break;
 -
 -                      /* redraw in progress parts */
 -                      elapsed = PIL_check_seconds_timer() - lastdraw;
 -                      if (elapsed > redrawtime) {
 -                              if (render_display_update_enabled(re))
 -                                      for (pa = re->parts.first; pa; pa = pa->next)
 -                                              if ((pa->status == PART_STATUS_IN_PROGRESS) && pa->nr && pa->result)
 -                                                      re->display_update(re->duh, pa->result, &pa->result->renrect);
 -
 -                              lastdraw = PIL_check_seconds_timer();
 -                      }
 -              }
 -
 -              BLI_threadpool_end(&threads);
 -
 -              if ((g_break=re->test_break(re->tbh)))
 -                      break;
 -      }
 -
 -      if (g_break) {
 -              /* review the done queue and handle all the render parts,
 -               * so no unfreed render result are lurking around
 -               */
 -              BLI_thread_queue_nowait(donequeue);
 -              while ((pa = BLI_thread_queue_pop(donequeue))) {
 -                      if (pa->result) {
 -                              render_result_free_list(&pa->fullresult, pa->result);
 -                              pa->result = NULL;
 -                      }
 -              }
 -      }
 -
 -      BLI_thread_queue_free(donequeue);
 -      BLI_thread_queue_free(workqueue);
 -
 -      if (re->result->do_exr_tile) {
 -              BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
 -              render_result_save_empty_result_tiles(re);
 -              BLI_rw_mutex_unlock(&re->resultmutex);
 -      }
 -
 -      /* unset threadsafety */
 -      g_break = 0;
 -      BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
 -      RE_parts_free(re);
 -      BLI_rw_mutex_unlock(&re->partsmutex);
 -      re->viewplane = viewplane; /* restore viewplane, modified by pano render */
 -}
 -
 -#ifdef WITH_FREESTYLE
 -static void init_freestyle(Render *re);
 -static void add_freestyle(Render *re, int render);
 -static void free_all_freestyle_renders(void);
 -#endif
 -
 -/* currently only called by preview renders and envmap */
 -void RE_TileProcessor(Render *re)
 -{
 -      main_render_result_new(re);
 -      threaded_tile_processor(re);
 -
 -      re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
 -      re->stats_draw(re->sdh, &re->i);
 -
 -#ifdef WITH_FREESTYLE
 -      /* Freestyle */
 -      if (re->r.mode & R_EDGE_FRS) {
 -              if (!re->test_break(re->tbh)) {
 -                      init_freestyle(re);
 -                      add_freestyle(re, 1);
 -                      free_all_freestyle_renders();
 -
 -                      re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
 -                      re->stats_draw(re->sdh, &re->i);
 -              }
 -      }
 -#endif
 -
 -}
 -
 -/* ************  This part uses API, for rendering Blender scenes ********** */
 -
 -static void do_render_3d(Render *re)
 -{
 -      RenderView *rv;
 -
 -      re->current_scene_update(re->suh, re->scene);
 -
 -      /* try external */
 -      if (RE_engine_render(re, 0))
 -              return;
 -
 -      /* internal */
 -      RE_parts_clamp(re);
 -
 -      /* add motion blur and fields offset to frames */
 -      const int cfra_backup = re->scene->r.cfra;
 -      const float subframe_backup = re->scene->r.subframe;
 -
 -      BKE_scene_frame_set(
 -              re->scene, (double)re->scene->r.cfra + (double)re->scene->r.subframe +
 -              (double)re->mblur_offs + (double)re->field_offs);
 -
 -      /* init main render result */
 -      main_render_result_new(re);
 -      if (re->result == NULL) {
 -              BKE_report(re->reports, RPT_ERROR, "Failed allocate render result, out of memory");
 -              G.is_break = true;
 -              return;
 -      }
 -
 -#ifdef WITH_FREESTYLE
 -      if (re->r.mode & R_EDGE_FRS) {
 -              init_freestyle(re);
 -      }
 -#endif
 -
 -      /* we need a new database for each view */
 -      for (rv = re->result->views.first; rv; rv = rv->next) {
 -              RE_SetActiveRenderView(re, rv->name);
 -
 -              /* lock drawing in UI during data phase */
 -              if (re->draw_lock)
 -                      re->draw_lock(re->dlh, 1);
 -
 -              /* make render verts/faces/halos/lamps */
 -              if (render_scene_needs_vector(re))
 -                      RE_Database_FromScene_Vectors(re, re->main, re->scene, re->lay);
 -              else {
 -                      RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
 -                      RE_Database_Preprocess(re);
 -              }
 -
 -              /* clear UI drawing locks */
 -              if (re->draw_lock)
 -                      re->draw_lock(re->dlh, 0);
 -
 -              threaded_tile_processor(re);
 -
 -#ifdef WITH_FREESTYLE
 -              /* Freestyle */
 -              if (re->r.mode & R_EDGE_FRS)
 -                      if (!re->test_break(re->tbh))
 -                              add_freestyle(re, 1);
 -#endif
 -
 -              /* do left-over 3d post effects (flares) */
 -              if (re->flag & R_HALO)
 -                      if (!re->test_break(re->tbh))
 -                              add_halo_flare(re);
 -
 -              /* free all render verts etc */
 -              RE_Database_Free(re);
 -      }
 -
 -      main_render_result_end(re);
 -
 -      re->scene->r.cfra = cfra_backup;
 -      re->scene->r.subframe = subframe_backup;
 -}
 -
 -/* called by blur loop, accumulate RGBA key alpha */
 -static void addblur_rect_key(RenderResult *rr, float *rectf, float *rectf1, float blurfac)
 -{
 -      float mfac = 1.0f - blurfac;
 -      int a, b, stride = 4 * rr->rectx;
 -      int len = stride * sizeof(float);
 -
 -      for (a = 0; a < rr->recty; a++) {
 -              if (blurfac == 1.0f) {
 -                      memcpy(rectf, rectf1, len);
 -              }
 -              else {
 -                      float *rf = rectf, *rf1 = rectf1;
 -
 -                      for (b = rr->rectx; b > 0; b--, rf += 4, rf1 += 4) {
 -                              if (rf1[3] < 0.01f)
 -                                      rf[3] = mfac * rf[3];
 -                              else if (rf[3] < 0.01f) {
 -                                      rf[0] = rf1[0];
 -                                      rf[1] = rf1[1];
 -                                      rf[2] = rf1[2];
 -                                      rf[3] = blurfac * rf1[3];
 -                              }
 -                              else {
 -                                      rf[0] = mfac * rf[0] + blurfac * rf1[0];
 -                                      rf[1] = mfac * rf[1] + blurfac * rf1[1];
 -                                      rf[2] = mfac * rf[2] + blurfac * rf1[2];
 -                                      rf[3] = mfac * rf[3] + blurfac * rf1[3];
 -                              }
 -                      }
 -              }
 -              rectf += stride;
 -              rectf1 += stride;
 -      }
 -}
 -
 -/* called by blur loop, accumulate renderlayers */
 -static void addblur_rect(RenderResult *rr, float *rectf, float *rectf1, float blurfac, int channels)
 -{
 -      float mfac = 1.0f - blurfac;
 -      int a, b, stride = channels * rr->rectx;
 -      int len = stride * sizeof(float);
 -
 -      for (a = 0; a < rr->recty; a++) {
 -              if (blurfac == 1.0f) {
 -                      memcpy(rectf, rectf1, len);
 -              }
 -              else {
 -                      float *rf = rectf, *rf1 = rectf1;
 -
 -                      for (b = rr->rectx * channels; b > 0; b--, rf++, rf1++) {
 -                              rf[0] = mfac * rf[0] + blurfac * rf1[0];
 -                      }
 -              }
 -              rectf += stride;
 -              rectf1 += stride;
 -      }
 -}
 -
 -
 -/* called by blur loop, accumulate renderlayers */
 -static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float blurfac, bool key_alpha)
 -{
 -      RenderLayer *rl, *rl1;
 -      RenderPass *rpass, *rpass1;
 -
 -      rl1 = brr->layers.first;
 -      for (rl = rr->layers.first; rl && rl1; rl = rl->next, rl1 = rl1->next) {
 -              /* passes are allocated in sync */
 -              rpass1 = rl1->passes.first;
 -              for (rpass = rl->passes.first; rpass && rpass1; rpass = rpass->next, rpass1 = rpass1->next) {
 -                      if (STREQ(rpass->name, RE_PASSNAME_COMBINED) && key_alpha)
 -                              addblur_rect_key(rr, rpass->rect, rpass1->rect, blurfac);
 -                      else
 -                              addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels);
 -              }
 -      }
 -}
 -
 -/* main blur loop, can be called by fields too */
 -static void do_render_blur_3d(Render *re)
 -{
 -      RenderResult *rres;
 -      float blurfac;
 -      int blur = re->r.mblur_samples;
 -
 -      /* create accumulation render result */
 -      rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
 -
 -      /* do the blur steps */
 -      while (blur--) {
 -              re->mblur_offs = re->r.blurfac * ((float)(re->r.mblur_samples - blur)) / (float)re->r.mblur_samples;
 -
 -              re->i.curblur = re->r.mblur_samples - blur;    /* stats */
 -
 -              do_render_3d(re);
 -
 -              blurfac = 1.0f / (float)(re->r.mblur_samples - blur);
 -
 -              merge_renderresult_blur(rres, re->result, blurfac, false);
 -              if (re->test_break(re->tbh)) break;
 -      }
 -
 -      /* swap results */
 -      BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
 -      render_result_free(re->result);
 -      re->result = rres;
 -      BLI_rw_mutex_unlock(&re->resultmutex);
 -
 -      re->mblur_offs = 0.0f;
 -      re->i.curblur = 0;   /* stats */
 -
 -      /* make sure motion blur changes get reset to current frame */
 -      if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0) {
 -              BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, re->lay);
 -      }
 -
 -      /* weak... the display callback wants an active renderlayer pointer... */
 -      re->result->renlay = render_get_active_layer(re, re->result);
 -      re->display_update(re->duh, re->result, NULL);
 -}
 -
 -
 -/* function assumes rectf1 and rectf2 to be half size of rectf */
 -static void interleave_rect(RenderResult *rr, float *rectf, float *rectf1, float *rectf2, int channels)
 -{
 -      int a, stride = channels * rr->rectx;
 -      int len = stride * sizeof(float);
 -
 -      for (a = 0; a < rr->recty; a += 2) {
 -              memcpy(rectf, rectf1, len);
 -              rectf += stride;
 -              rectf1 += stride;
 -              memcpy(rectf, rectf2, len);
 -              rectf += stride;
 -              rectf2 += stride;
 -      }
 +      re->progress = f;
 +      re->prh = handle;
  }
  
 -/* merge render results of 2 fields */
 -static void merge_renderresult_fields(RenderResult *rr, RenderResult *rr1, RenderResult *rr2)
 +void RE_draw_lock_cb(Render *re, void *handle, void (*f)(void *handle, int i))
  {
 -      RenderLayer *rl, *rl1, *rl2;
 -      RenderPass *rpass, *rpass1, *rpass2;
 -
 -      rl1 = rr1->layers.first;
 -      rl2 = rr2->layers.first;
 -      for (rl = rr->layers.first; rl && rl1 && rl2; rl = rl->next, rl1 = rl1->next, rl2 = rl2->next) {
 -
 -              /* passes are allocated in sync */
 -              rpass1 = rl1->passes.first;
 -              rpass2 = rl2->passes.first;
 -              for (rpass = rl->passes.first;
 -                   rpass && rpass1 && rpass2;
 -                   rpass = rpass->next, rpass1 = rpass1->next, rpass2 = rpass2->next)
 -              {
 -                      interleave_rect(rr, rpass->rect, rpass1->rect, rpass2->rect, rpass->channels);
 -              }
 -      }
 +      re->draw_lock = f;
 +      re->dlh = handle;
  }
  
 -
 -/* interleaves 2 frames */
 -static void do_render_fields_3d(Render *re)
 +void RE_test_break_cb(Render *re, void *handle, int (*f)(void *handle))
  {
 -      Object *camera = RE_GetCamera(re);
 -      RenderResult *rr1, *rr2 = NULL;
 -
 -      /* no render result was created, we can safely halve render y */
 -      re->winy /= 2;
 -      re->recty /= 2;
 -      re->disprect.ymin /= 2;
 -      re->disprect.ymax /= 2;
 -
 -      re->i.curfield = 1;  /* stats */
 -
 -      /* first field, we have to call camera routine for correct aspect and subpixel offset */
 -      RE_SetCamera(re, camera);
 -      if (re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE) == 0)
 -              do_render_blur_3d(re);
 -      else
 -              do_render_3d(re);
 -
 -      BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
 -      rr1 = re->result;
 -      re->result = NULL;
 -      BLI_rw_mutex_unlock(&re->resultmutex);
 -
 -      /* second field */
 -      if (!re->test_break(re->tbh)) {
 -
 -              re->i.curfield = 2;  /* stats */
 -
 -              re->flag |= R_SEC_FIELD;
 -              if ((re->r.mode & R_FIELDSTILL) == 0) {
 -                      re->field_offs = 0.5f;
 -              }
 -              RE_SetCamera(re, camera);
 -              if (re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE) == 0)
 -                      do_render_blur_3d(re);
 -              else
 -                      do_render_3d(re);
 -              re->flag &= ~R_SEC_FIELD;
 -
 -              re->field_offs = 0.0f;
 -
 -              rr2 = re->result;
 -      }
 +      re->test_break = f;
 +      re->tbh = handle;
 +}
  
 -      /* allocate original height new buffers */
 -      re->winy *= 2;
 -      re->recty *= 2;
 -      re->disprect.ymin *= 2;
 -      re->disprect.ymax *= 2;
  
 -      BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
 -      re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS);
 +/* ********* add object data (later) ******** */
  
 -      if (rr2) {
 -              if (re->r.mode & R_ODDFIELD)
 -                      merge_renderresult_fields(re->result, rr2, rr1);
 -              else
 -                      merge_renderresult_fields(re->result, rr1, rr2);
 +/* object is considered fully prepared on correct time etc */
 +/* includes lights */
 +#if 0
 +void RE_AddObject(Render *UNUSED(re), Object *UNUSED(ob))
 +{
-       
 -              render_result_free(rr2);
 -      }
 +}
 +#endif
  
 -      render_result_free(rr1);
 +/* *************************************** */
  
 -      re->i.curfield = 0;  /* stats */
 +#ifdef WITH_FREESTYLE
 +static void init_freestyle(Render *re);
 +static void add_freestyle(Render *re, int render);
 +static void free_all_freestyle_renders(void);
 +#endif
  
 -      /* weak... the display callback wants an active renderlayer pointer... */
 -      re->result->renlay = render_get_active_layer(re, re->result);
  
 -      BLI_rw_mutex_unlock(&re->resultmutex);
 +/* ************  This part uses API, for rendering Blender scenes ********** */
  
 -      re->display_update(re->duh, re->result, NULL);
 +static void do_render_3d(Render *re)
 +{
 +      re->current_scene_update(re->suh, re->scene);
 +      RE_engine_render(re, 0);
  }
  
  /* make sure disprect is not affected by the render border */
@@@ -1121,9 -1939,14 +1121,9 @@@ static void do_render(Render *re
  
        /* now use renderdata and camera to set viewplane */
        RE_SetCamera(re, camera);
-       
 -      if (re->r.mode & R_FIELDS)
 -              do_render_fields_3d(re);
 -      else if (re->r.mode & R_MBLUR && (re->r.scemode & R_FULL_SAMPLE) == 0)
 -              do_render_blur_3d(re);
 -      else
 -              do_render_3d(re);
 +      do_render_3d(re);
-       
        /* when border render, check if we have to insert it in black */
        render_result_uncrop(re);
  }
@@@ -1146,9 -1969,9 +1146,9 @@@ static void render_scene(Render *re, Sc
                winx = (sce->r.size * sce->r.xsch) / 100;
                winy = (sce->r.size * sce->r.ysch) / 100;
        }
-       
        /* initial setup */
 -      RE_InitState(resc, re, &sce->r, NULL, winx, winy, &re->disprect);
 +      RE_InitState(resc, re, &sce->r, &sce->view_layers, NULL, winx, winy, &re->disprect);
  
        /* We still want to use 'rendercache' setting from org (main) scene... */
        resc->r.scemode = (resc->r.scemode & ~R_EXR_CACHE_FILE) | (re->r.scemode & R_EXR_CACHE_FILE);
        resc->main = re->main;
        resc->scene = sce;
        resc->lay = sce->lay;
-       
 -      resc->scene_color_manage = BKE_scene_check_color_management_enabled(sce);
        /* ensure scene has depsgraph, base flags etc OK */
        BKE_scene_set_background(re->main, sce);
  
        resc->sdh = re->sdh;
        resc->current_scene_update = re->current_scene_update;
        resc->suh = re->suh;
-       
 -      do_render_fields_blur_3d(resc);
 +      do_render(resc);
  }
  
  /* helper call to detect if this scene needs a render, or if there's a any render layer to render */
@@@ -1334,14 -2162,17 +1334,14 @@@ static void tag_scenes_for_render(Rende
  {
        bNode *node;
        Scene *sce;
-       
 -#ifdef DEPSGRAPH_WORKAROUND_HACK
 -      int renderlay = re->lay;
 -#endif
        for (sce = re->main->scene.first; sce; sce = sce->id.next) {
                sce->id.tag &= ~LIB_TAG_DOIT;
  #ifdef DEPSGRAPH_WORKAROUND_HACK
 -              tag_dependend_objects_for_render(re->main, sce, renderlay);
 +              tag_dependend_objects_for_render(re->main, sce);
  #endif
        }
-       
  #ifdef WITH_FREESTYLE
        if (re->freestyle_bmain) {
                for (sce = re->freestyle_bmain->scene.first; sce; sce = sce->id.next) {
        if (RE_GetCamera(re) && composite_needs_render(re->scene, 1)) {
                re->scene->id.tag |= LIB_TAG_DOIT;
  #ifdef DEPSGRAPH_WORKAROUND_HACK
 -              tag_dependend_objects_for_render(re->main, re->scene, renderlay);
 +              tag_dependend_objects_for_render(re->main, re->scene);
  #endif
        }
-       
        if (re->scene->nodetree == NULL) return;
-       
        /* check for render-layers nodes using other scenes, we tag them LIB_TAG_DOIT */
        for (node = re->scene->nodetree->nodes.first; node; node = node->next) {
                node->flag &= ~NODE_TEST;
@@@ -1406,15 -2237,11 +1406,15 @@@ static void ntree_render_scenes(Render 
        int cfra = re->scene->r.cfra;
        Scene *restore_scene = re->scene;
        bool scene_changed = false;
-       
        if (re->scene->nodetree == NULL) return;
-       
        tag_scenes_for_render(re);
  
-       
 +#ifdef DEPSGRAPH_WORKAROUND_GROUP_HACK
 +      tag_collections_for_render(re);
 +#endif
++
        /* now foreach render-result node tagged we do a full render */
        /* results are stored in a way compisitor will find it */
        for (node = re->scene->nodetree->nodes.first; node; node = node->next) {
@@@ -1586,19 -2671,28 +1586,19 @@@ static void do_render_composite(Render 
                                ntree->stats_draw = render_composit_stats;
                                ntree->test_break = re->test_break;
                                ntree->progress = re->progress;
 -                              ntree->sdh = re->sdh;
 +                              ntree->sdh = re;
                                ntree->tbh = re->tbh;
                                ntree->prh = re->prh;
-                               
 -                              /* in case it was never initialized */
 -                              R.sdh = re->sdh;
 -                              R.stats_draw = re->stats_draw;
 -                              R.i.starttime = re->i.starttime;
 -                              R.i.cfra = re->i.cfra;
 -
 -                              if (update_newframe)
 -                                      BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, re->lay);
 +                              if (update_newframe) {
 +                                      /* If we have consistent depsgraph now would be a time to update them. */
 +                              }
-                               
 -                              if (re->r.scemode & R_FULL_SAMPLE)
 -                                      do_merge_fullsample(re, ntree);
 -                              else {
 -                                      RenderView *rv;
 -                                      for (rv = re->result->views.first; rv; rv = rv->next) {
 -                                              ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings, rv->name);
 -                                      }
 +                              RenderView *rv;
 +                              for (rv = re->result->views.first; rv; rv = rv->next) {
 +                                      ntreeCompositExecTree(re->scene, ntree, &re->r, true, G.background == 0, &re->scene->view_settings, &re->scene->display_settings, rv->name);
                                }
-                               
                                ntree->stats_draw = NULL;
                                ntree->test_break = NULL;
                                ntree->progress = NULL;
@@@ -1815,13 -2896,18 +1815,13 @@@ static void do_render_all_options(Rende
                re->display_update(re->duh, re->result, NULL);
        }
        else {
 -              re->pool = BKE_image_pool_new();
 -
 -              do_render_composite_fields_blur_3d(re);
 -
 -              BKE_image_pool_free(re->pool);
 -              re->pool = NULL;
 +              do_render_composite(re);
        }
-       
        re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
-       
        re->stats_draw(re->sdh, &re->i);
-       
        /* save render result stamp if needed */
        if (re->result != NULL) {
                camera = RE_GetCamera(re);
@@@ -1972,10 -3070,10 +1972,10 @@@ static int check_composite_output(Scen
        return node_tree_has_composite_output(scene->nodetree);
  }
  
 -bool RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *reports)
 +bool RE_is_rendering_allowed(Scene *scene, ViewLayer *single_layer, Object *camera_override, ReportList *reports)
  {
        int scemode = check_mode_full_sample(&scene->r);
-       
        if (scene->r.mode & R_BORDER) {
                if (scene->r.border.xmax <= scene->r.border.xmin ||
                    scene->r.border.ymax <= scene->r.border.ymin)
                        BKE_report(reports, RPT_ERROR, "Cannot save render buffers, check the temp default path");
                        return 0;
                }
 -
 -              /* no fullsample and edge */
 -              if ((scemode & R_FULL_SAMPLE) && (scene->r.mode & R_EDGE)) {
 -                      BKE_report(reports, RPT_ERROR, "Full sample does not support edge enhance");
 -                      return 0;
 -              }
 -
        }
-       
        if (scemode & R_DOCOMP) {
                if (scene->use_nodes) {
                        if (!scene->nodetree) {
@@@ -2119,9 -3237,10 +2119,9 @@@ static int render_initialize_from_main(
                disprect.xmax = winx;
                disprect.ymax = winy;
        }
-       
        re->main = bmain;
        re->scene = scene;
 -      re->scene_color_manage = BKE_scene_check_color_management_enabled(scene);
        re->camera_override = camera_override;
        re->lay = lay_override ? lay_override : scene->lay;
        re->layer_override = lay_override;
         */
        if (0) {
                /* make sure dynamics are up to date */
 -              update_physics_cache(re, scene, anim_init);
 +              ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
 +              update_physics_cache(re, scene, view_layer, anim_init);
        }
-       
 -      if (srl || scene->r.scemode & R_SINGLE_LAYER) {
 +      if (single_layer || scene->r.scemode & R_SINGLE_LAYER) {
                BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
                render_result_single_layer_begin(re);
                BLI_rw_mutex_unlock(&re->resultmutex);
        }
-       
 -      RE_InitState(re, NULL, &scene->r, srl, winx, winy, &disprect);
 +      RE_InitState(re, NULL, &scene->r, &scene->view_layers, single_layer, winx, winy, &disprect);
        if (!re->ok)  /* if an error was printed, abort */
                return 0;
-       
        /* initstate makes new result, have to send changed tags around */
        ntreeCompositTagRender(re->scene);
  
@@@ -2188,12 -3301,10 +2188,12 @@@ void RE_BlenderFrame(Render *re, Main *
  
        /* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */
        G.is_rendering = true;
-       
        scene->r.cfra = frame;
-       
 -      if (render_initialize_from_main(re, &scene->r, bmain, scene, srl, camera_override, lay_override, 0, 0)) {
 +      if (render_initialize_from_main(re, &scene->r, bmain, scene, single_layer,
 +                                      camera_override, lay_override, 0, 0))
 +      {
                MEM_reset_peak_memory();
  
                BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
@@@ -2838,9 -3951,10 +2838,9 @@@ bool RE_ReadRenderResult(Scene *scene, 
        re = RE_GetSceneRender(scene);
        if (re == NULL)
                re = RE_NewSceneRender(scene);
 -      RE_InitState(re, NULL, &scene->r, NULL, winx, winy, &disprect);
 +      RE_InitState(re, NULL, &scene->r, &scene->view_layers, NULL, winx, winy, &disprect);
        re->scene = scene;
-       
 -      re->scene_color_manage = BKE_scene_check_color_management_enabled(scene);
        BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
        success = render_result_exr_file_cache_read(re);
        BLI_rw_mutex_unlock(&re->resultmutex);
@@@ -283,19 -318,19 +283,19 @@@ static void pointdensity_cache_vertex_c
        const MLoopCol *mcol;
        char layername[MAX_CUSTOMDATA_LAYER_NAME];
        int i;
-       
        BLI_assert(data_color);
-       
 -      if (!CustomData_has_layer(&dm->loopData, CD_MLOOPCOL))
 +      if (!CustomData_has_layer(&mesh->ldata, CD_MLOOPCOL))
                return;
 -      CustomData_validate_layer_name(&dm->loopData, CD_MLOOPCOL, pd->vertex_attribute_name, layername);
 -      mcol = CustomData_get_layer_named(&dm->loopData, CD_MLOOPCOL, layername);
 +      CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPCOL, pd->vertex_attribute_name, layername);
 +      mcol = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPCOL, layername);
        if (!mcol)
                return;
-       
        /* Stores the number of MLoops using the same vertex, so we can normalize colors. */
        int *mcorners = MEM_callocN(sizeof(int) * pd->totpoints, "point density corner count");
-       
        for (i = 0; i < totloop; i++) {
                int v = mloop[i].v;
  
@@@ -328,10 -363,10 +328,10 @@@ static void pointdensity_cache_vertex_w
        const MDeformVert *mdef, *dv;
        int mdef_index;
        int i;
-       
        BLI_assert(data_color);
-       
 -      mdef = CustomData_get_layer(&dm->vertData, CD_MDEFORMVERT);
 +      mdef = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT);
        if (!mdef)
                return;
        mdef_index = defgroup_name_index(ob, pd->vertex_attribute_name);
        }
  }
  
 -static void pointdensity_cache_vertex_normal(PointDensity *pd, Object *UNUSED(ob), DerivedMesh *dm, float *data_color)
 +static void pointdensity_cache_vertex_normal(PointDensity *pd, Object *UNUSED(ob), Mesh *mesh, float *data_color)
  {
 -      MVert *mvert = dm->getVertArray(dm), *mv;
 +      MVert *mvert = mesh->mvert, *mv;
        int i;
-       
        BLI_assert(data_color);
-       
        for (i = 0, mv = mvert; i < pd->totpoints; i++, mv++, data_color += 3) {
                normal_short_to_float_v3(data_color, mv->no);
        }
@@@ -413,16 -457,16 +413,16 @@@ static void pointdensity_cache_object(P
  
                BLI_bvhtree_insert(pd->point_tree, i, co, 1);
        }
-       
        switch (pd->ob_color_source) {
                case TEX_PD_COLOR_VERTCOL:
 -                      pointdensity_cache_vertex_color(pd, ob, dm, data_color);
 +                      pointdensity_cache_vertex_color(pd, ob, mesh, data_color);
                        break;
                case TEX_PD_COLOR_VERTWEIGHT:
 -                      pointdensity_cache_vertex_weight(pd, ob, dm, data_color);
 +                      pointdensity_cache_vertex_weight(pd, ob, mesh, data_color);
                        break;
                case TEX_PD_COLOR_VERTNOR:
 -                      pointdensity_cache_vertex_normal(pd, ob, dm, data_color);
 +                      pointdensity_cache_vertex_normal(pd, ob, mesh, data_color);
                        break;
        }
  
@@@ -266,14 -266,16 +266,14 @@@ RenderResult *render_result_new(Render 
        RenderResult *rr;
        RenderLayer *rl;
        RenderView *rv;
 -      SceneRenderLayer *srl;
        int rectx, recty;
-       
 -      int nr;
        rectx = BLI_rcti_size_x(partrct);
        recty = BLI_rcti_size_y(partrct);
-       
        if (rectx <= 0 || recty <= 0)
                return NULL;
-       
        rr = MEM_callocN(sizeof(RenderResult), "new render result");
        rr->rectx = rectx;
        rr->recty = recty;
  
                rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
                BLI_addtail(&rr->layers, rl);
-               
 -              BLI_strncpy(rl->name, srl->name, sizeof(rl->name));
 -              rl->lay = srl->lay;
 -              rl->lay_zmask = srl->lay_zmask;
 -              rl->lay_exclude = srl->lay_exclude;
 -              rl->layflag = srl->layflag;
 -              rl->passflag = srl->passflag; /* for debugging: srl->passflag | SCE_PASS_RAYHITS; */
 -              rl->pass_xor = srl->pass_xor;
 -              rl->light_override = srl->light_override;
 -              rl->mat_override = srl->mat_override;
 +              BLI_strncpy(rl->name, view_layer->name, sizeof(rl->name));
 +              rl->layflag = view_layer->layflag;
 +              rl->passflag = view_layer->passflag; /* for debugging: view_layer->passflag | SCE_PASS_RAYHITS; */
 +              rl->pass_xor = view_layer->pass_xor;
                rl->rectx = rectx;
                rl->recty = recty;
-               
                if (rr->do_exr_tile) {
                        rl->display_buffer = MEM_mapallocN((size_t)rectx * recty * sizeof(unsigned int),
                                                           "Combined display space rgba");
                }
  
                /* note, this has to be in sync with scene.c */
 -              rl->lay = (1 << 20) - 1;
                rl->layflag = 0x7FFF;    /* solid ztra halo strand */
                rl->passflag = SCE_PASS_COMBINED;
-               
 -              re->r.actlay = 0;
 +              re->active_view_layer = 0;
        }
-       
        /* border render; calculate offset for use in compositor. compo is centralized coords */
        /* XXX obsolete? I now use it for drawing border render offset (ton) */
        rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2);
@@@ -980,13 -1010,13 +980,13 @@@ void render_result_single_layer_end(Ren
        if (re->pushedresult->rectx == re->result->rectx && re->pushedresult->recty == re->result->recty) {
                /* find which layer in re->pushedresult should be replaced */
                rl = re->result->layers.first;
-               
                /* render result should be empty after this */
                BLI_remlink(&re->result->layers, rl);
-               
                /* reconstruct render result layers */
 -              for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) {
 -                      if (nr == re->r.actlay) {
 +              for (nr = 0, view_layer = re->view_layers.first; view_layer; view_layer = view_layer->next, nr++) {
 +                      if (nr == re->active_view_layer) {
                                BLI_addtail(&re->result->layers, rl);
                        }
                        else {
@@@ -714,18 -784,113 +714,18 @@@ static int cubemap_glob(const float n[3
  /* ------------------------------------------------------------------------- */
  
  static void do_2d_mapping(
 -        const MTex *mtex, float texvec[3], VlakRen *vlr, const float n[3], float dxt[3], float dyt[3])
 +        const MTex *mtex, float texvec[3], const float n[3], float dxt[3], float dyt[3])
  {
        Tex *tex;
 -      Object *ob= NULL;
        float fx, fy, fac1, area[8];
 -      int ok, proj, areaflag= 0, wrap, texco;
 +      int ok, proj, areaflag= 0, wrap;
-       
        /* mtex variables localized, only cubemap doesn't cooperate yet... */
        wrap= mtex->mapping;
        tex= mtex->tex;
 -      ob= mtex->object;
 -      texco= mtex->texco;
  
 -      if (R.osa==0) {
 +      if (!(dxt && dyt)) {
-               
                if (wrap==MTEX_FLAT) {
                        fx = (texvec[0] + 1.0f) / 2.0f;
                        fy = (texvec[1] + 1.0f) / 2.0f;
                else if (wrap == MTEX_TUBE)   map_to_tube( &fx, &fy, texvec[0], texvec[1], texvec[2]);
                else if (wrap == MTEX_SPHERE) map_to_sphere(&fx, &fy, texvec[0], texvec[1], texvec[2]);
                else {
 -                      if      (texco == TEXCO_OBJECT) cubemap_ob(ob, n, texvec[0], texvec[1], texvec[2], &fx, &fy);
 -                      else if (texco == TEXCO_GLOB)   cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy);
 -                      else                            cubemap(mtex, vlr, n, texvec[0], texvec[1], texvec[2], &fx, &fy);
 +                      cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy);
                }
-               
                /* repeat */
                if (tex->extend==TEX_REPEAT) {
                        if (tex->xrepeat>1) {
@@@ -953,11 -1122,10 +953,11 @@@ static int multitex(Tex *tex
        int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */
  
        texres->talpha = false;  /* is set when image texture returns alpha (considered premul) */
-       
        if (use_nodes && tex->use_nodes && tex->nodetree) {
 +              const float cfra = 1.0f; /* This was only set for Blender Internal render before. */
                retval = ntreeTexExecTree(tex->nodetree, texres, texvec, dxt, dyt, osatex, thread,
 -                                        tex, which_output, R.r.cfra, texnode_preview, NULL, NULL);
 +                                        tex, which_output, cfra, texnode_preview, NULL);
        }
        else {
                switch (tex->type) {
@@@ -1091,9 -1272,9 +1091,9 @@@ static int multitex_nodes_intern(Tex *t
                                          texnode_preview,
                                          use_nodes);
  
 -                      if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) {
 +                      if (mtex->mapto & (MAP_COL)) {
                                ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
-                               
                                /* don't linearize float buffers, assumed to be linear */
                                if (ibuf != NULL &&
                                    ibuf->rect_float == NULL &&
                                zero_v3(dxt_l);
                                zero_v3(dyt_l);
                        }
-                       
 -                      do_2d_mapping(&localmtex, texvec_l, NULL, NULL, dxt_l, dyt_l);
 +                      do_2d_mapping(&localmtex, texvec_l, NULL, dxt_l, dyt_l);
                        rgbnor = multitex(tex,
                                          texvec_l,
                                          dxt_l, dyt_l,
@@@ -1445,65 -1652,2008 +1445,65 @@@ float texture_value_blend(float tex, fl
        return in;
  }
  
 -static void texco_mapping(ShadeInput *shi, Tex *tex, MTex *mtex,
 -                          const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3])
 -{
 -      /* new: first swap coords, then map, then trans/scale */
 -      if (tex->type == TEX_IMAGE) {
 -              /* placement */
 -              texvec[0] = mtex->projx ? co[mtex->projx - 1] : 0.f;
 -              texvec[1] = mtex->projy ? co[mtex->projy - 1] : 0.f;
 -              texvec[2] = mtex->projz ? co[mtex->projz - 1] : 0.f;
 -
 -              if (shi->osatex) {
 -                      if (mtex->projx) {
 -                              dxt[0] = dx[mtex->projx - 1];
 -                              dyt[0] = dy[mtex->projx - 1];
 -                      }
 -                      else dxt[0] = dyt[0] = 0.f;
 -                      if (mtex->projy) {
 -                              dxt[1] = dx[mtex->projy - 1];
 -                              dyt[1] = dy[mtex->projy - 1];
 -                      }
 -                      else dxt[1] = dyt[1] = 0.f;
 -                      if (mtex->projz) {
 -                              dxt[2] = dx[mtex->projz - 1];
 -                              dyt[2] = dy[mtex->projz - 1];
 -                      }
 -                      else dxt[2] = dyt[2] = 0.f;
 -              }
 -              do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt);
 -
 -              /* translate and scale */
 -              texvec[0] = mtex->size[0]*(texvec[0] - 0.5f) + mtex->ofs[0] + 0.5f;
 -              texvec[1] = mtex->size[1]*(texvec[1] - 0.5f) + mtex->ofs[1] + 0.5f;
 -              if (shi->osatex) {
 -                      dxt[0] = mtex->size[0] * dxt[0];
 -                      dxt[1] = mtex->size[1] * dxt[1];
 -                      dyt[0] = mtex->size[0] * dyt[0];
 -                      dyt[1] = mtex->size[1] * dyt[1];
 -              }
 -
 -              /* problem: repeat-mirror is not a 'repeat' but 'extend' in imagetexture.c */
 -              /* TXF: bug was here, only modify texvec when repeat mode set, old code affected other modes too.
 -               * New texfilters solve mirroring differently so that it also works correctly when
 -               * textures are scaled (sizeXYZ) as well as repeated. See also modification in do_2d_mapping().
 -               * (since currently only done in osa mode, results will look incorrect without osa TODO) */
 -              if (tex->extend == TEX_REPEAT && (tex->flag & TEX_REPEAT_XMIR)) {
 -                      if (tex->texfilter == TXF_BOX)
 -                              texvec[0] -= floorf(texvec[0]);  /* this line equivalent to old code, same below */
 -                      else if (texvec[0] < 0.f || texvec[0] > 1.f) {
 -                              const float tx = 0.5f*texvec[0];
 -                              texvec[0] = 2.f*(tx - floorf(tx));
 -                              if (texvec[0] > 1.f) texvec[0] = 2.f - texvec[0];
 -                      }
 -              }
 -              if (tex->extend == TEX_REPEAT && (tex->flag & TEX_REPEAT_YMIR)) {
 -                      if (tex->texfilter == TXF_BOX)
 -                              texvec[1] -= floorf(texvec[1]);
 -                      else if (texvec[1] < 0.f || texvec[1] > 1.f) {
 -                              const float ty = 0.5f*texvec[1];
 -                              texvec[1] = 2.f*(ty - floorf(ty));
 -                              if (texvec[1] > 1.f) texvec[1] = 2.f - texvec[1];
 -                      }
 -              }
 -
 -      }
 -      else {  /* procedural */
 -              /* placement */
 -              texvec[0] = mtex->size[0]*(mtex->projx ? (co[mtex->projx - 1] + mtex->ofs[0]) : mtex->ofs[0]);
 -              texvec[1] = mtex->size[1]*(mtex->projy ? (co[mtex->projy - 1] + mtex->ofs[1]) : mtex->ofs[1]);
 -              texvec[2] = mtex->size[2]*(mtex->projz ? (co[mtex->projz - 1] + mtex->ofs[2]) : mtex->ofs[2]);
 -
 -              if (shi->osatex) {
 -                      if (mtex->projx) {
 -                              dxt[0] = mtex->size[0]*dx[mtex->projx - 1];
 -                              dyt[0] = mtex->size[0]*dy[mtex->projx - 1];
 -                      }
 -                      else dxt[0] = dyt[0] = 0.f;
 -                      if (mtex->projy) {
 -                              dxt[1] = mtex->size[1]*dx[mtex->projy - 1];
 -                              dyt[1] = mtex->size[1]*dy[mtex->projy - 1];
 -                      }
 -                      else dxt[1] = dyt[1] = 0.f;
 -                      if (mtex->projz) {
 -                              dxt[2] = mtex->size[2]*dx[mtex->projz - 1];
 -                              dyt[2] = mtex->size[2]*dy[mtex->projz - 1];
 -                      }
 -                      else dxt[2]= dyt[2] = 0.f;
 -              }
 -
 -              if (mtex->tex->type == TEX_ENVMAP) {
 -                      EnvMap *env = tex->env;
 -                      if (!env->object) {
 -                              // env->object is a view point for envmap rendering
 -                              // if it's not set, return the result depending on the world_space_shading flag
 -                              if (BKE_scene_use_world_space_shading(R.scene)) {
 -                                      mul_mat3_m4_v3(R.viewinv, texvec);
 -                                      if (shi->osatex) {
 -                                              mul_mat3_m4_v3(R.viewinv, dxt);
 -                                              mul_mat3_m4_v3(R.viewinv, dyt);
 -                                      }
 -                              }
 -                      }
 -              }
 -      }
 -}
 -
 -/* Bump code from 2.5 development cycle, has a number of bugs, but here for compatibility */
 -
 -typedef struct CompatibleBump {
 -      float nu[3], nv[3], nn[3];
 -      float dudnu, dudnv, dvdnu, dvdnv;
 -      bool nunvdone;
 -} CompatibleBump;
 -
 -static void compatible_bump_init(CompatibleBump *compat_bump)
 -{
 -      memset(compat_bump, 0, sizeof(*compat_bump));
 -
 -      compat_bump->dudnu = 1.0f;
 -      compat_bump->dvdnv = 1.0f;
 -}
 -
 -static void compatible_bump_uv_derivs(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, int i)
 -{
 -      /* uvmapping only, calculation of normal tangent u/v partial derivatives
 -       * (should not be here, dudnu, dudnv, dvdnu & dvdnv should probably be part of ShadeInputUV struct,
 -       *  nu/nv in ShadeInput and this calculation should then move to shadeinput.c,
 -       * shade_input_set_shade_texco() func.) */
 -
 -      /* NOTE: test for shi->obr->ob here,
 -       * since vlr/obr/obi can be 'fake' when called from fastshade(), another reason to move it.. */
 -
 -      /* NOTE: shi->v1 is NULL when called from displace_render_vert,
 -       * assigning verts in this case is not trivial because the shi quad face side is not know. */
 -      if ((mtex->texflag & MTEX_COMPAT_BUMP) && shi->obr && shi->obr->ob && shi->v1) {
 -              if (mtex->mapto & (MAP_NORM|MAP_WARP) && !((mtex->tex->type==TEX_IMAGE) && (mtex->tex->imaflag & TEX_NORMALMAP))) {
 -                      MTFace* tf = RE_vlakren_get_tface(shi->obr, shi->vlr, i, NULL, 0);
 -                      int j1 = shi->i1, j2 = shi->i2, j3 = shi->i3;
 -
 -                      vlr_set_uv_indices(shi->vlr, &j1, &j2, &j3);
 -
 -                      /* compute ortho basis around normal */
 -                      if (!compat_bump->nunvdone) {
 -                              /* render normal is negated */
 -                              compat_bump->nn[0] = -shi->vn[0];
 -                              compat_bump->nn[1] = -shi->vn[1];
 -                              compat_bump->nn[2] = -shi->vn[2];
 -                              ortho_basis_v3v3_v3(compat_bump->nu, compat_bump->nv, compat_bump->nn);
 -                              compat_bump->nunvdone = true;
 -                      }
 -
 -                      if (tf) {
 -                              const float *uv1 = tf->uv[j1], *uv2 = tf->uv[j2], *uv3 = tf->uv[j3];
 -                              const float an[3] = {fabsf(compat_bump->nn[0]), fabsf(compat_bump->nn[1]), fabsf(compat_bump->nn[2])};
 -                              const int a1 = (an[0] > an[1] && an[0] > an[2]) ? 1 : 0;
 -                              const int a2 = (an[2] > an[0] && an[2] > an[1]) ? 1 : 2;
 -                              const float dp1_a1 = shi->v1->co[a1] - shi->v3->co[a1];
 -                              const float dp1_a2 = shi->v1->co[a2] - shi->v3->co[a2];
 -                              const float dp2_a1 = shi->v2->co[a1] - shi->v3->co[a1];
 -                              const float dp2_a2 = shi->v2->co[a2] - shi->v3->co[a2];
 -                              const float du1 = uv1[0] - uv3[0], du2 = uv2[0] - uv3[0];
 -                              const float dv1 = uv1[1] - uv3[1], dv2 = uv2[1] - uv3[1];
 -                              const float dpdu_a1 = dv2*dp1_a1 - dv1*dp2_a1;
 -                              const float dpdu_a2 = dv2*dp1_a2 - dv1*dp2_a2;
 -                              const float dpdv_a1 = du1*dp2_a1 - du2*dp1_a1;
 -                              const float dpdv_a2 = du1*dp2_a2 - du2*dp1_a2;
 -                              float d = dpdu_a1*dpdv_a2 - dpdv_a1*dpdu_a2;
 -                              float uvd = du1*dv2 - dv1*du2;
 -
 -                              if (uvd == 0.f) uvd = 1e-5f;
 -                              if (d == 0.f) d = 1e-5f;
 -                              d = uvd / d;
 -
 -                              compat_bump->dudnu = (dpdv_a2*compat_bump->nu[a1] - dpdv_a1*compat_bump->nu[a2])*d;
 -                              compat_bump->dvdnu = (dpdu_a1*compat_bump->nu[a2] - dpdu_a2*compat_bump->nu[a1])*d;
 -                              compat_bump->dudnv = (dpdv_a2*compat_bump->nv[a1] - dpdv_a1*compat_bump->nv[a2])*d;
 -                              compat_bump->dvdnv = (dpdu_a1*compat_bump->nv[a2] - dpdu_a2*compat_bump->nv[a1])*d;
 -                      }
 -              }
 -      }
 -}
 -
 -static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres,
 -                                   float Tnor, const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3],
 -                                   struct ImagePool *pool, const bool skip_load_image)
 -{
 -      TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL};  /* temp TexResult */
 -      float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv;
 -      const int fromrgb = ((tex->type == TEX_IMAGE) || ((tex->flag & TEX_COLORBAND)!=0));
 -      const float bf = -0.04f*Tnor*mtex->norfac;
 -      int rgbnor;
 -      /* disable internal bump eval */
 -      float *nvec = texres->nor;
 -      texres->nor = NULL;
 -      /* du & dv estimates, constant value defaults */
 -      du = dv = 0.01f;
 -
 -      /* compute ortho basis around normal */
 -      if (!compat_bump->nunvdone) {
 -              /* render normal is negated */
 -              negate_v3_v3(compat_bump->nn, shi->vn);
 -              ortho_basis_v3v3_v3(compat_bump->nu, compat_bump->nv, compat_bump->nn);
 -              compat_bump->nunvdone = true;
 -      }
 -
 -      /* two methods, either constant based on main image resolution,
 -       * (which also works without osa, though of course not always good (or even very bad) results),
 -       * or based on tex derivative max values (osa only). Not sure which is best... */
 -
 -      if (!shi->osatex && (tex->type == TEX_IMAGE) && tex->ima) {
 -              /* in case we have no proper derivatives, fall back to
 -               * computing du/dv it based on image size */
 -              ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
 -              if (ibuf) {
 -                      du = 1.f/(float)ibuf->x;
 -                      dv = 1.f/(float)ibuf->y;
 -              }
 -              BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
 -      }
 -      else if (shi->osatex) {
 -              /* we have derivatives, can compute proper du/dv */
 -              if (tex->type == TEX_IMAGE) {   /* 2d image, use u & v max. of dx/dy 2d vecs */
 -                      const float adx[2] = {fabsf(dx[0]), fabsf(dx[1])};
 -                      const float ady[2] = {fabsf(dy[0]), fabsf(dy[1])};
 -                      du = MAX2(adx[0], ady[0]);
 -                      dv = MAX2(adx[1], ady[1]);
 -              }
 -              else {  /* 3d procedural, estimate from all dx/dy elems */
 -                      const float adx[3] = {fabsf(dx[0]), fabsf(dx[1]), fabsf(dx[2])};
 -                      const float ady[3] = {fabsf(dy[0]), fabsf(dy[1]), fabsf(dy[2])};
 -                      du = max_fff(adx[0], adx[1], adx[2]);
 -                      dv = max_fff(ady[0], ady[1], ady[2]);
 -              }
 -      }
 -
 -      /* center, main return value */
 -      texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
 -      rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool, skip_load_image);
 -      cd = fromrgb ? (texres->tr + texres->tg + texres->tb) / 3.0f : texres->tin;
 -
 -      if (mtex->texco == TEXCO_UV) {
 -              /* for the uv case, use the same value for both du/dv,
 -               * since individually scaling the normal derivatives makes them useless... */
 -              du = min_ff(du, dv);
 -              idu = (du < 1e-5f) ? bf : (bf/du);
 -
 -              /* +u val */
 -              tco[0] = co[0] + compat_bump->dudnu*du;
 -              tco[1] = co[1] + compat_bump->dvdnu*du;
 -              tco[2] = 0.f;
 -              texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
 -              multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
 -              ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
 -
 -              /* +v val */
 -              tco[0] = co[0] + compat_bump->dudnv*du;
 -              tco[1] = co[1] + compat_bump->dvdnv*du;
 -              tco[2] = 0.f;
 -              texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
 -              multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
 -              vd = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
 -      }
 -      else {
 -              float tu[3], tv[3];
 -
 -              copy_v3_v3(tu, compat_bump->nu);
 -              copy_v3_v3(tv, compat_bump->nv);
 -
 -              idu = (du < 1e-5f) ? bf : (bf/du);
 -              idv = (dv < 1e-5f) ? bf : (bf/dv);
 -
 -              if ((mtex->texco == TEXCO_ORCO) && shi->obr && shi->obr->ob) {
 -                      mul_mat3_m4_v3(shi->obr->ob->imat_ren, tu);
 -                      mul_mat3_m4_v3(shi->obr->ob->imat_ren, tv);
 -                      normalize_v3(tu);
 -                      normalize_v3(tv);
 -              }
 -              else if (mtex->texco == TEXCO_GLOB) {
 -                      mul_mat3_m4_v3(R.viewinv, tu);
 -                      mul_mat3_m4_v3(R.viewinv, tv);
 -              }
 -              else if (mtex->texco == TEXCO_OBJECT && mtex->object) {
 -                      mul_mat3_m4_v3(mtex->object->imat_ren, tu);
 -                      mul_mat3_m4_v3(mtex->object->imat_ren, tv);
 -                      normalize_v3(tu);
 -                      normalize_v3(tv);
 -              }
 -
 -              /* +u val */
 -              tco[0] = co[0] + tu[0]*du;
 -              tco[1] = co[1] + tu[1]*du;
 -              tco[2] = co[2] + tu[2]*du;
 -              texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
 -              multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
 -              ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
 -
 -              /* +v val */
 -              tco[0] = co[0] + tv[0]*dv;
 -              tco[1] = co[1] + tv[1]*dv;
 -              tco[2] = co[2] + tv[2]*dv;
 -              texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt);
 -              multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool, skip_load_image);
 -              vd = idv*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
 -      }
 -
 -      /* bumped normal */
 -      compat_bump->nu[0] += ud*compat_bump->nn[0];
 -      compat_bump->nu[1] += ud*compat_bump->nn[1];
 -      compat_bump->nu[2] += ud*compat_bump->nn[2];
 -      compat_bump->nv[0] += vd*compat_bump->nn[0];
 -      compat_bump->nv[1] += vd*compat_bump->nn[1];
 -      compat_bump->nv[2] += vd*compat_bump->nn[2];
 -      cross_v3_v3v3(nvec, compat_bump->nu, compat_bump->nv);
 -
 -      nvec[0] = -nvec[0];
 -      nvec[1] = -nvec[1];
 -      nvec[2] = -nvec[2];
 -      texres->nor = nvec;
 -
 -      rgbnor |= TEX_NOR;
 -      return rgbnor;
 -}
 -
 -/* Improved bump code from later in 2.5 development cycle */
 -
 -typedef struct NTapBump {
 -      int init_done;
 -      int iPrevBumpSpace;     /* 0: uninitialized, 1: objectspace, 2: texturespace, 4: viewspace */
 -      /* bumpmapping */
 -      float vNorg[3]; /* backup copy of shi->vn */
 -      float vNacc[3]; /* original surface normal minus the surface gradient of every bump map which is encountered */
 -      float vR1[3], vR2[3]; /* cross products (sigma_y, original_normal), (original_normal, sigma_x) */
 -      float sgn_det; /* sign of the determinant of the matrix {sigma_x, sigma_y, original_normal} */
 -      float fPrevMagnitude; /* copy of previous magnitude, used for multiple bumps in different spaces */
 -} NTapBump;
 -
 -static void ntap_bump_init(NTapBump *ntap_bump)
 -{
 -      memset(ntap_bump, 0, sizeof(*ntap_bump));
 -}
 +/* ------------------------------------------------------------------------- */
  
 -static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres,
 -                             float Tnor, const float co[3], const float dx[3], const float dy[3],
 -                             float texvec[3], float dxt[3], float dyt[3], struct ImagePool *pool,
 -                             const bool skip_load_image)
 +int externtex(const MTex *mtex,
 +              const float vec[3],
 +              float *tin, float *tr, float *tg, float *tb, float *ta,
 +              const int thread,
 +              struct ImagePool *pool,
 +              const bool skip_load_image,
 +              const bool texnode_preview)
  {
 -      TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL};        /* temp TexResult */
 -
 -      const int fromrgb = ((tex->type == TEX_IMAGE) || ((tex->flag & TEX_COLORBAND)!=0));
 -
 -      /* The negate on Hscale is done because the
 -       * normal in the renderer points inward which corresponds
 -       * to inverting the bump map. The normals are generated
 -       * this way in calc_vertexnormals(). Should this ever change
 -       * this negate must be removed. */
 -      float Hscale = -Tnor*mtex->norfac;
 -
 -      int dimx=512, dimy=512;
 -      const int imag_tspace_dimension_x = 1024;  /* only used for texture space variant */
 -      float aspect = 1.0f;
 -
 -      /* 2 channels for 2D texture and 3 for 3D textures. */
 -      const int nr_channels = (mtex->texco == TEXCO_UV)? 2 : 3;
 -      int c, rgbnor, iBumpSpace;
 -      float dHdx, dHdy;
 -      int found_deriv_map = (tex->type==TEX_IMAGE) && (tex->imaflag & TEX_DERIVATIVEMAP);
 -
 -      /* disable internal bump eval in sampler, save pointer */
 -      float *nvec = texres->nor;
 -      texres->nor = NULL;
 -
 -      if (found_deriv_map==0) {
 -              if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {
 -                      if (tex->ima)
 -                              Hscale *= 13.0f; /* appears to be a sensible default value */
 -              }
 -              else
 -                      Hscale *= 0.1f; /* factor 0.1 proved to look like the previous bump code */
 -      }
 -
 -      if ( !ntap_bump->init_done ) {
 -              copy_v3_v3(ntap_bump->vNacc, shi->vn);
 -              copy_v3_v3(ntap_bump->vNorg, shi->vn);
 -              ntap_bump->fPrevMagnitude = 1.0f;
 -              ntap_bump->iPrevBumpSpace = 0;
 -
 -              ntap_bump->init_done = true;
 -      }
 -
 -      /* resolve image dimensions */
 -      if (found_deriv_map || (mtex->texflag&MTEX_BUMP_TEXTURESPACE)!=0) {
 -              ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
 -              if (ibuf) {
 -                      dimx = ibuf->x;
 -                      dimy = ibuf->y;
 -                      aspect = ((float) dimy) / dimx;
 -              }
 -              BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
 -      }
 +      Tex *tex;
 +      TexResult texr;
 +      float dxt[3], dyt[3], texvec[3];
 +      int rgb;
-       
 -      if (found_deriv_map) {
 -              float dBdu, dBdv, auto_bump = 1.0f;
 -              float s = 1;            /* negate this if flipped texture coordinate */
 -              texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
 -              rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool, skip_load_image);
 +      tex= mtex->tex;
 +      if (tex==NULL) return 0;
 +      texr.nor= NULL;
-       
 -              if (shi->obr->ob->derivedFinal) {
 -                      auto_bump = shi->obr->ob->derivedFinal->auto_bump_scale;
 -              }
 +      /* placement */
 +      if (mtex->projx) texvec[0]= mtex->size[0]*(vec[mtex->projx-1]+mtex->ofs[0]);
 +      else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
-       
 -              {
 -                      float fVirtDim = sqrtf(fabsf((float) (dimx*dimy)*mtex->size[0]*mtex->size[1]));
 -                      auto_bump /= MAX2(fVirtDim, FLT_EPSILON);
 -              }
 +      if (mtex->projy) texvec[1]= mtex->size[1]*(vec[mtex->projy-1]+mtex->ofs[1]);
 +      else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
-       
 -              /* this variant using a derivative map is described here
 -               * http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html */
 -              dBdu = auto_bump*Hscale*dimx*(2*texres->tr-1);
 -              dBdv = auto_bump*Hscale*dimy*(2*texres->tg-1);
 +      if (mtex->projz) texvec[2]= mtex->size[2]*(vec[mtex->projz-1]+mtex->ofs[2]);
 +      else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
-       
 -              dHdx = dBdu*dxt[0] + s * dBdv*dxt[1];
 -              dHdy = dBdu*dyt[0] + s * dBdv*dyt[1];
 +      /* texture */
 +      if (tex->type==TEX_IMAGE) {
 +              do_2d_mapping(mtex, texvec, NULL, dxt, dyt);
        }
-       
 -      else if (!(mtex->texflag & MTEX_5TAP_BUMP)) {
 -              /* compute height derivatives with respect to output image pixel coordinates x and y */
 -              float STll[3], STlr[3], STul[3];
 -              float Hll, Hlr, Hul;
 -
 -              texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
 -
 -              for (c=0; c<nr_channels; c++) {
 -                      /* dx contains the derivatives (du/dx, dv/dx)
 -                       * dy contains the derivatives (du/dy, dv/dy) */
 -                      STll[c] = texvec[c];
 -                      STlr[c] = texvec[c]+dxt[c];
 -                      STul[c] = texvec[c]+dyt[c];
 -              }
 -
 -              /* clear unused derivatives */
 -              for (c=nr_channels; c<3; c++) {
 -                      STll[c] = 0.0f;
 -                      STlr[c] = 0.0f;
 -                      STul[c] = 0.0f;
 -              }
 -              /* use texres for the center sample, set rgbnor */
 -              rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres, pool, skip_load_image);
 -              Hll = (fromrgb) ? IMB_colormanagement_get_luminance(&texres->tr) : texres->tin;
 -
 -              /* use ttexr for the other 2 taps */
 -              multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr, pool, skip_load_image);
 -              Hlr = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
 -
 -              multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr, pool, skip_load_image);
 -              Hul = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
 +      rgb = multitex(tex,
 +                     texvec,
 +                     dxt, dyt,
 +                     0, &texr,
 +                     thread,
 +                     mtex->which_output,
 +                     pool,
 +                     skip_load_image,
 +                     texnode_preview,
 +                     true);
-       
 -              dHdx = Hscale*(Hlr - Hll);
 -              dHdy = Hscale*(Hul - Hll);
 +      if (rgb) {
 +              texr.tin = IMB_colormanagement_get_luminance(&texr.tr);
        }
        else {
 -              /* same as above, but doing 5 taps, increasing quality at cost of speed */
 -              float STc[3], STl[3], STr[3], STd[3], STu[3];
 -              float /* Hc, */ /* UNUSED */  Hl, Hr, Hd, Hu;
 -
 -              texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
 -
 -              for (c=0; c<nr_channels; c++) {
 -                      STc[c] = texvec[c];
 -                      STl[c] = texvec[c] - 0.5f*dxt[c];
 -                      STr[c] = texvec[c] + 0.5f*dxt[c];
 -                      STd[c] = texvec[c] - 0.5f*dyt[c];
 -                      STu[c] = texvec[c] + 0.5f*dyt[c];
 -              }
 -
 -              /* clear unused derivatives */
 -              for (c=nr_channels; c<3; c++) {
 -                      STc[c] = 0.0f;
 -                      STl[c] = 0.0f;
 -                      STr[c] = 0.0f;
 -                      STd[c] = 0.0f;
 -                      STu[c] = 0.0f;
 -              }
 -
 -              /* use texres for the center sample, set rgbnor */
 -              rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres, pool, skip_load_image);
 -              /* Hc = (fromrgb) ? IMB_colormanagement_get_luminance(&texres->tr) : texres->tin; */ /* UNUSED */
 -
 -              /* use ttexr for the other taps */
 -              multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr, pool, skip_load_image);
 -              Hl = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
 -              multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr, pool, skip_load_image);
 -              Hr = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
 -              multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr, pool, skip_load_image);
 -              Hd = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
 -              multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr, pool, skip_load_image);
 -              Hu = (fromrgb) ? IMB_colormanagement_get_luminance(&ttexr.tr) : ttexr.tin;
 -
 -              dHdx = Hscale*(Hr - Hl);
 -              dHdy = Hscale*(Hu - Hd);
 -      }
 -
 -      /* restore pointer */
 -      texres->nor = nvec;
 -
 -      /* replaced newbump with code based on listing 1 and 2 of
 -       * [Mik10] Mikkelsen M. S.: Bump Mapping Unparameterized Surfaces on the GPU.
 -       * -> http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf */
 -
 -      if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE )
 -              iBumpSpace = 1;
 -      else if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
 -              iBumpSpace = 2;
 -      else
 -              iBumpSpace = 4; /* ViewSpace */
 -
 -      if ( ntap_bump->iPrevBumpSpace != iBumpSpace ) {
 -
 -              /* initialize normal perturbation vectors */
 -              int xyz;
 -              float fDet, abs_fDet, fMagnitude;
 -              /* object2view and inverted matrix */
 -              float obj2view[3][3], view2obj[3][3], tmp[4][4];
 -              /* local copies of derivatives and normal */
 -              float dPdx[3], dPdy[3], vN[3];
 -              copy_v3_v3(dPdx, shi->dxco);
 -              copy_v3_v3(dPdy, shi->dyco);
 -              copy_v3_v3(vN, ntap_bump->vNorg);
 -
 -              if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) {
 -                      /* TODO: these calculations happen for every pixel!
 -                       *      -> move to shi->obi */
 -                      mul_m4_m4m4(tmp, R.viewmat, shi->obr->ob->obmat);
 -                      copy_m3_m4(obj2view, tmp); /* use only upper left 3x3 matrix */
 -                      invert_m3_m3(view2obj, obj2view);
 -
 -                      /* generate the surface derivatives in object space */
 -                      mul_m3_v3(view2obj, dPdx);
 -                      mul_m3_v3(view2obj, dPdy);
 -                      /* generate the unit normal in object space */
 -                      mul_transposed_m3_v3(obj2view, vN);
 -                      normalize_v3(vN);
 -              }
 -
 -              cross_v3_v3v3(ntap_bump->vR1, dPdy, vN);
 -              cross_v3_v3v3(ntap_bump->vR2, vN, dPdx);
 -              fDet = dot_v3v3(dPdx, ntap_bump->vR1);
 -              ntap_bump->sgn_det = (fDet < 0)? -1.0f: 1.0f;
 -              abs_fDet = ntap_bump->sgn_det * fDet;
 -
 -              if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {
 -                      if (tex->ima) {
 -                              /* crazy hack solution that gives results similar to normal mapping - part 1 */
 -                              normalize_v3(ntap_bump->vR1);
 -                              normalize_v3(ntap_bump->vR2);
 -                              abs_fDet = 1.0f;
 -                      }
 -              }
 -
 -              fMagnitude = abs_fDet;
 -              if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE ) {
 -                      /* pre do transform of texres->nor by the inverse transposed of obj2view */
 -                      mul_transposed_m3_v3(view2obj, vN);
 -                      mul_transposed_m3_v3(view2obj, ntap_bump->vR1);
 -                      mul_transposed_m3_v3(view2obj, ntap_bump->vR2);
 -
 -                      fMagnitude *= len_v3(vN);
 -              }
 -
 -              if (ntap_bump->fPrevMagnitude > 0.0f)
 -                      for (xyz=0; xyz<3; xyz++)
 -                              ntap_bump->vNacc[xyz] *= fMagnitude / ntap_bump->fPrevMagnitude;
 -
 -              ntap_bump->fPrevMagnitude = fMagnitude;
 -              ntap_bump->iPrevBumpSpace = iBumpSpace;
 -      }
 -
 -      if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {
 -              if (tex->ima) {
 -                      /* crazy hack solution that gives results similar to normal mapping - part 2 */
 -                      float vec[2];
 -                      const float imag_tspace_dimension_y = aspect*imag_tspace_dimension_x;
 -
 -                      vec[0] = imag_tspace_dimension_x*dxt[0];
 -                      vec[1] = imag_tspace_dimension_y*dxt[1];
 -                      dHdx *= 1.0f/len_v2(vec);
 -                      vec[0] = imag_tspace_dimension_x*dyt[0];
 -                      vec[1] = imag_tspace_dimension_y*dyt[1];
 -                      dHdy *= 1.0f/len_v2(vec);
 -              }
 -      }
 -
 -      /* subtract the surface gradient from vNacc */
 -      for (c=0; c<3; c++) {
 -              float vSurfGrad_compi = ntap_bump->sgn_det * (dHdx * ntap_bump->vR1[c] + dHdy * ntap_bump->vR2[c]);
 -              ntap_bump->vNacc[c] -= vSurfGrad_compi;
 -              texres->nor[c] = ntap_bump->vNacc[c]; /* copy */
 +              texr.tr= mtex->r;
 +              texr.tg= mtex->g;
 +              texr.tb= mtex->b;
        }
-       
 -      rgbnor |= TEX_NOR;
 -      return rgbnor;
 -}
 -
 -void do_material_tex(ShadeInput *shi, Render *re)
 -{
 -      const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0;
 -      CompatibleBump compat_bump;
 -      NTapBump ntap_bump;
 -      MTex *mtex;
 -      Tex *tex;
 -      TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
 -      float *co = NULL, *dx = NULL, *dy = NULL;
 -      float fact, facm, factt, facmm, stencilTin=1.0;
 -      float texvec[3], dxt[3], dyt[3], tempvec[3], norvec[3], warpvec[3]={0.0f, 0.0f, 0.0f}, Tnor=1.0;
 -      int tex_nr, rgbnor= 0;
 -      bool warp_done = false, use_compat_bump = false, use_ntap_bump = false;
 -      bool found_nmapping = false, found_deriv_map = false;
 -      bool iFirstTimeNMap = true;
 -
 -      compatible_bump_init(&compat_bump);
 -      ntap_bump_init(&ntap_bump);
 -
 -      if (re->r.scemode & R_NO_TEX) return;
 -      /* here: test flag if there's a tex (todo) */
 -
 -      for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
 -
 -              /* separate tex switching */
 -              if (shi->mat->septex & (1<<tex_nr)) continue;
 -
 -              if (shi->mat->mtex[tex_nr]) {
 -                      mtex= shi->mat->mtex[tex_nr];
 -
 -                      tex= mtex->tex;
 -                      if (tex == NULL) continue;
 -
 -                      found_deriv_map = (tex->type==TEX_IMAGE) && (tex->imaflag & TEX_DERIVATIVEMAP);
 -                      use_compat_bump= (mtex->texflag & MTEX_COMPAT_BUMP) != 0;
 -                      use_ntap_bump = ((mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP))!=0 || found_deriv_map!=0) ? true : false;
 -
 -                      /* XXX texture node trees don't work for this yet */
 -                      if (tex->nodetree && tex->use_nodes) {
 -                              use_compat_bump = false;
 -                              use_ntap_bump = false;
 -                      }
 -
 -                      /* case displacement mapping */
 -                      if (shi->osatex == 0 && use_ntap_bump) {
 -                              use_ntap_bump = false;
 -                              use_compat_bump = true;
 -                      }
 -
 -                      /* case ocean */
 -                      if (tex->type == TEX_OCEAN) {
 -                              use_ntap_bump = false;
 -                              use_compat_bump = false;
 -                      }
 -
 -                      /* which coords */
 -                      if (mtex->texco==TEXCO_ORCO) {
 -                              if (mtex->texflag & MTEX_DUPLI_MAPTO) {
 -                                      co= shi->duplilo; dx= dxt; dy= dyt;
 -                                      dxt[0]= dxt[1]= dxt[2]= 0.0f;
 -                                      dyt[0]= dyt[1]= dyt[2]= 0.0f;
 -                              }
 -                              else {
 -                                      co= shi->lo; dx= shi->dxlo; dy= shi->dylo;
 -                              }
 -                      }
 -                      else if (mtex->texco==TEXCO_OBJECT) {
 -                              Object *ob= mtex->object;
 -                              if (ob) {
 -                                      co= tempvec;
 -                                      dx= dxt;
 -                                      dy= dyt;
 -                                      copy_v3_v3(tempvec, shi->co);
 -                                      if (mtex->texflag & MTEX_OB_DUPLI_ORIG)
 -                                              if (shi->obi && shi->obi->duplitexmat)
 -                                                      mul_m4_v3(shi->obi->duplitexmat, tempvec);
 -                                      mul_m4_v3(ob->imat_ren, tempvec);
 -                                      if (shi->osatex) {
 -                                              copy_v3_v3(dxt, shi->dxco);
 -                                              copy_v3_v3(dyt, shi->dyco);
 -                                              mul_mat3_m4_v3(ob->imat_ren, dxt);
 -                                              mul_mat3_m4_v3(ob->imat_ren, dyt);
 -                                      }
 -                              }
 -                              else {
 -                                      /* if object doesn't exist, do not use orcos (not initialized) */
 -                                      co= shi->co;
 -                                      dx= shi->dxco; dy= shi->dyco;
 -                              }
 -                      }
 -                      else if (mtex->texco==TEXCO_REFL) {
 -                              calc_R_ref(shi);
 -                              co= shi->ref; dx= shi->dxref; dy= shi->dyref;
 -                      }
 -                      else if (mtex->texco==TEXCO_NORM) {
 -                              co= shi->orn; dx= shi->dxno; dy= shi->dyno;
 -                      }
 -                      else if (mtex->texco==TEXCO_TANGENT) {
 -                              co= shi->tang; dx= shi->dxno; dy= shi->dyno;
 -                      }
 -                      else if (mtex->texco==TEXCO_GLOB) {
 -                              co= shi->gl; dx= shi->dxgl; dy= shi->dygl;
 -                      }
 -                      else if (mtex->texco==TEXCO_UV) {
 -                              if (mtex->texflag & MTEX_DUPLI_MAPTO) {
 -                                      co= shi->dupliuv; dx= dxt; dy= dyt;
 -                                      dxt[0]= dxt[1]= dxt[2]= 0.0f;
 -                                      dyt[0]= dyt[1]= dyt[2]= 0.0f;
 -                              }
 -                              else {
 -                                      ShadeInputUV *suv= &shi->uv[shi->actuv];
 -                                      int i = shi->actuv;
 -
 -                                      if (mtex->uvname[0] != 0) {
 -                                              for (i = 0; i < shi->totuv; i++) {
 -                                                      if (STREQ(shi->uv[i].name, mtex->uvname)) {
 -                                                              suv= &shi->uv[i];
 -                                                              break;
 -                                                      }
 -                                              }
 -                                      }
 -
 -                                      co= suv->uv;
 -                                      dx= suv->dxuv;
 -                                      dy= suv->dyuv;
 -
 -                                      compatible_bump_uv_derivs(&compat_bump, shi, mtex, i);
 -                              }
 -                      }
 -                      else if (mtex->texco==TEXCO_WINDOW) {
 -                              co= shi->winco; dx= shi->dxwin; dy= shi->dywin;
 -                      }
 -                      else if (mtex->texco==TEXCO_STRAND) {
 -                              co= tempvec; dx= dxt; dy= dyt;
 -                              co[0]= shi->strandco;
 -                              co[1]= co[2]= 0.0f;
 -                              dx[0]= shi->dxstrand;
 -                              dx[1]= dx[2]= 0.0f;
 -                              dy[0]= shi->dystrand;
 -                              dy[1]= dy[2]= 0.0f;
 -                      }
 -                      else if (mtex->texco==TEXCO_STRESS) {
 -                              co= tempvec; dx= dxt; dy= dyt;
 -                              co[0]= shi->stress;
 -                              co[1]= co[2]= 0.0f;
 -                              dx[0]= 0.0f;
 -                              dx[1]= dx[2]= 0.0f;
 -                              dy[0]= 0.0f;
 -                              dy[1]= dy[2]= 0.0f;
 -                      }
 -                      else {
 -                              continue;  /* can happen when texco defines disappear and it renders old files */
 -                      }
 -
 -                      /* the pointer defines if bumping happens */
 -                      if (mtex->mapto & (MAP_NORM|MAP_WARP)) {
 -                              texres.nor= norvec;
 -                              norvec[0]= norvec[1]= norvec[2]= 0.0;
 -                      }
 -                      else texres.nor= NULL;
 -
 -                      if (warp_done) {
 -                              add_v3_v3v3(tempvec, co, warpvec);
 -                              co= tempvec;
 -                      }
 -
 -                      /* XXX texture node trees don't work for this yet */
 -                      if (texres.nor && !((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP))) {
 -                              if (use_compat_bump) {
 -                                      rgbnor = compatible_bump_compute(&compat_bump, shi, mtex, tex,
 -                                                                       &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
 -                                                                       re->pool, skip_load_image);
 -                              }
 -                              else if (use_ntap_bump) {
 -                                      rgbnor = ntap_bump_compute(&ntap_bump, shi, mtex, tex,
 -                                                                 &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
 -                                                                 re->pool, skip_load_image);
 -                              }
 -                              else {
 -                                      texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
 -                                      rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool, skip_load_image);
 -                              }
 -                      }
 -                      else {
 -                              texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
 -                              rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool, skip_load_image);
 -                      }
 -
 -                      /* texture output */
 -
 -                      if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
 -                              texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
 -                              rgbnor -= TEX_RGB;
 -                      }
 -                      if (mtex->texflag & MTEX_NEGATIVE) {
 -                              if (rgbnor & TEX_RGB) {
 -                                      texres.tr= 1.0f-texres.tr;
 -                                      texres.tg= 1.0f-texres.tg;
 -                                      texres.tb= 1.0f-texres.tb;
 -                              }
 -                              texres.tin= 1.0f-texres.tin;
 -                      }
 -                      if (mtex->texflag & MTEX_STENCIL) {
 -                              if (rgbnor & TEX_RGB) {
 -                                      fact= texres.ta;
 -                                      texres.ta*= stencilTin;
 -                                      stencilTin*= fact;
 -                              }
 -                              else {
 -                                      fact= texres.tin;
 -                                      texres.tin*= stencilTin;
 -                                      stencilTin*= fact;
 -                              }
 -                      }
 -                      else {
 -                              Tnor*= stencilTin;
 -                      }
 -
 -                      if (texres.nor) {
 -                              if ((rgbnor & TEX_NOR)==0) {
 -                                      /* make our own normal */
 -                                      if (rgbnor & TEX_RGB) {
 -                                              copy_v3_v3(texres.nor, &texres.tr);
 -                                      }
 -                                      else {
 -                                              float co_nor= 0.5f * cosf(texres.tin - 0.5f);
 -                                              float si = 0.5f * sinf(texres.tin - 0.5f);
 -                                              float f1, f2;
 -
 -                                              f1= shi->vn[0];
 -                                              f2= shi->vn[1];
 -                                              texres.nor[0]= f1*co_nor+f2*si;
 -                                              f1= shi->vn[1];
 -                                              f2= shi->vn[2];
 -                                              texres.nor[1]= f1*co_nor+f2*si;
 -                                              texres.nor[2]= f2*co_nor-f1*si;
 -                                      }
 -                              }
 -                              /* warping, local space */
 -                              if (mtex->mapto & MAP_WARP) {
 -                                      float *warpnor= texres.nor, warpnor_[3];
 -
 -                                      if (use_ntap_bump) {
 -                                              copy_v3_v3(warpnor_, texres.nor);
 -                                              warpnor= warpnor_;
 -                                              normalize_v3(warpnor_);
 -                                      }
 -                                      warpvec[0]= mtex->warpfac*warpnor[0];
 -                                      warpvec[1]= mtex->warpfac*warpnor[1];
 -                                      warpvec[2]= mtex->warpfac*warpnor[2];
 -                                      warp_done = true;
 -                              }
 -#if 0
 -                              if (mtex->texflag & MTEX_VIEWSPACE) {
 -                                      /* rotate to global coords */
 -                                      if (mtex->texco==TEXCO_ORCO || mtex->texco==TEXCO_UV) {
 -                                              if (shi->vlr && shi->obr && shi->obr->ob) {
 -                                                      float len= normalize_v3(texres.nor);
 -                                                      /* can be optimized... (ton) */
 -                                                      mul_mat3_m4_v3(shi->obr->ob->obmat, texres.nor);
 -                                                      mul_mat3_m4_v3(re->viewmat, texres.nor);
 -                                                      normalize_v3_length(texres.nor, len);
 -                                              }
 -                                      }
 -                              }
 -#endif
 -                      }
 -
 -                      /* mapping */
 -                      if (mtex->mapto & (MAP_COL | MAP_COLSPEC | MAP_COLMIR)) {
 -                              float tcol[3];
 -
 -                              /* stencil maps on the texture control slider, not texture intensity value */
 -                              copy_v3_v3(tcol, &texres.tr);
 -
 -                              if ((rgbnor & TEX_RGB) == 0) {
 -                                      copy_v3_v3(tcol, &mtex->r);
 -                              }
 -                              else if (mtex->mapto & MAP_ALPHA) {
 -                                      texres.tin = stencilTin;
 -                              }
 -                              else {
 -                                      texres.tin = texres.ta;
 -                              }
 -
 -                              /* inverse gamma correction */
 -                              if (tex->type==TEX_IMAGE) {
 -                                      Image *ima = tex->ima;
 -                                      ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, re->pool);
 -
 -                                      /* don't linearize float buffers, assumed to be linear */
 -                                      if (ibuf != NULL &&
 -                                          ibuf->rect_float == NULL &&
 -                                          (rgbnor & TEX_RGB) &&
 -                                          R.scene_color_manage)
 -                                      {
 -                                              IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace);
 -                                      }
 -
 -                                      BKE_image_pool_release_ibuf(ima, ibuf, re->pool);
 -                              }
 -
 -                              if (mtex->mapto & MAP_COL) {
 -                                      float colfac= mtex->colfac*stencilTin;
 -                                      texture_rgb_blend(&shi->r, tcol, &shi->r, texres.tin, colfac, mtex->blendtype);
 -                              }
 -                              if (mtex->mapto & MAP_COLSPEC) {
 -                                      float colspecfac= mtex->colspecfac*stencilTin;
 -                                      texture_rgb_blend(&shi->specr, tcol, &shi->specr, texres.tin, colspecfac, mtex->blendtype);
 -                              }
 -                              if (mtex->mapto & MAP_COLMIR) {
 -                                      float mirrfac= mtex->mirrfac*stencilTin;
 -
 -                                      /* exception for envmap only */
 -                                      if (tex->type==TEX_ENVMAP && mtex->blendtype==MTEX_BLEND) {
 -                                              fact= texres.tin*mirrfac;
 -                                              facm= 1.0f- fact;
 -                                              shi->refcol[0]= fact + facm*shi->refcol[0];
 -                                              shi->refcol[1]= fact*tcol[0] + facm*shi->refcol[1];
 -                                              shi->refcol[2]= fact*tcol[1] + facm*shi->refcol[2];
 -                                              shi->refcol[3]= fact*tcol[2] + facm*shi->refcol[3];
 -                                      }
 -                                      else {
 -                                              texture_rgb_blend(&shi->mirr, tcol, &shi->mirr, texres.tin, mirrfac, mtex->blendtype);
 -                                      }
 -                              }
 -                      }
 -                      if ( (mtex->mapto & MAP_NORM) ) {
 -                              if (texres.nor) {
 -                                      float norfac= mtex->norfac;
 -
 -                                      /* we need to code blending modes for normals too once.. now 1 exception hardcoded */
 -
 -                                      if ((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP)) {
 -
 -                                              found_nmapping = 1;
 -
 -                                              /* qdn: for normalmaps, to invert the normalmap vector,
 -                                               * it is better to negate x & y instead of subtracting the vector as was done before */
 -                                              if (norfac < 0.0f) {
 -                                                      texres.nor[0] = -texres.nor[0];
 -                                                      texres.nor[1] = -texres.nor[1];
 -                                              }
 -                                              fact = Tnor*fabsf(norfac);
 -                                              if (fact>1.f) fact = 1.f;
 -                                              facm = 1.f-fact;
 -                                              if (mtex->normapspace == MTEX_NSPACE_TANGENT) {
 -                                                      /* qdn: tangent space */
 -                                                      float B[3], tv[3];
 -                                                      const float *no = iFirstTimeNMap ? shi->nmapnorm : shi->vn;
 -                                                      iFirstTimeNMap = false;
 -                                                      cross_v3_v3v3(B, no, shi->nmaptang);    /* bitangent */
 -                                                      mul_v3_fl(B, shi->nmaptang[3]);
 -                                                      /* transform norvec from tangent space to object surface in camera space */
 -                                                      tv[0] = texres.nor[0]*shi->nmaptang[0] + texres.nor[1]*B[0] + texres.nor[2]*no[0];
 -                                                      tv[1] = texres.nor[0]*shi->nmaptang[1] + texres.nor[1]*B[1] + texres.nor[2]*no[1];
 -                                                      tv[2] = texres.nor[0]*shi->nmaptang[2] + texres.nor[1]*B[2] + texres.nor[2]*no[2];
 -                                                      shi->vn[0]= facm*no[0] + fact*tv[0];
 -                                                      shi->vn[1]= facm*no[1] + fact*tv[1];
 -                                                      shi->vn[2]= facm*no[2] + fact*tv[2];
 -                                              }
 -                                              else {
 -                                                      float nor[3];
 -
 -                                                      copy_v3_v3(nor, texres.nor);
 -
 -                                                      if (mtex->normapspace == MTEX_NSPACE_CAMERA) {
 -                                                              /* pass */
 -                                                      }
 -                                                      else if (mtex->normapspace == MTEX_NSPACE_WORLD) {
 -                                                              mul_mat3_m4_v3(re->viewmat, nor);
 -                                                      }
 -                                                      else if (mtex->normapspace == MTEX_NSPACE_OBJECT) {
 -                                                              if (shi->obr && shi->obr->ob)
 -                                                                      mul_mat3_m4_v3(shi->obr->ob->obmat, nor);
 -                                                              mul_mat3_m4_v3(re->viewmat, nor);
 -                                                      }
 -
 -                                                      normalize_v3(nor);
 -
 -                                                      /* qdn: worldspace */
 -                                                      shi->vn[0]= facm*shi->vn[0] + fact*nor[0];
 -                                                      shi->vn[1]= facm*shi->vn[1] + fact*nor[1];
 -                                                      shi->vn[2]= facm*shi->vn[2] + fact*nor[2];
 -                                              }
 -                                      }
 -                                      else {
 -                                              /* XXX texture node trees don't work for this yet */
 -                                              if (use_compat_bump || use_ntap_bump) {
 -                                                      shi->vn[0] = texres.nor[0];
 -                                                      shi->vn[1] = texres.nor[1];
 -                                                      shi->vn[2] = texres.nor[2];
 -                                              }
 -                                              else {
 -                                                      float nor[3], dot;
 -
 -                                                      if (shi->mat->mode & MA_TANGENT_V) {
 -                                                              shi->tang[0]+= Tnor*norfac*texres.nor[0];
 -                                                              shi->tang[1]+= Tnor*norfac*texres.nor[1];
 -                                                              shi->tang[2]+= Tnor*norfac*texres.nor[2];
 -                                                      }
 -
 -                                                      /* prevent bump to become negative normal */
 -                                                      nor[0]= Tnor*norfac*texres.nor[0];
 -                                                      nor[1]= Tnor*norfac*texres.nor[1];
 -                                                      nor[2]= Tnor*norfac*texres.nor[2];
 -
 -                                                      dot= 0.5f + 0.5f * dot_v3v3(nor, shi->vn);
 -
 -                                                      shi->vn[0]+= dot*nor[0];
 -                                                      shi->vn[1]+= dot*nor[1];
 -                                                      shi->vn[2]+= dot*nor[2];
 -                                              }
 -                                      }
 -                                      normalize_v3(shi->vn);
 -
 -                                      /* this makes sure the bump is passed on to the next texture */
 -                                      shi->orn[0]= -shi->vn[0];
 -                                      shi->orn[1]= -shi->vn[1];
 -                                      shi->orn[2]= -shi->vn[2];
 -                              }
 -                      }
 -
 -                      if ( mtex->mapto & MAP_DISPLACE ) {
 -                              /* Now that most textures offer both Nor and Intensity, allow  */
 -                              /* both to work, and let user select with slider.   */
 -                              if (texres.nor) {
 -                                      float norfac= mtex->norfac;
 -
 -                                      shi->displace[0]+= 0.2f*Tnor*norfac*texres.nor[0];
 -                                      shi->displace[1]+= 0.2f*Tnor*norfac*texres.nor[1];
 -                                      shi->displace[2]+= 0.2f*Tnor*norfac*texres.nor[2];
 -                              }
 -
 -                              if (rgbnor & TEX_RGB) {
 -                                      texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
 -                              }
 -
 -                              factt= (0.5f-texres.tin)*mtex->dispfac*stencilTin; facmm= 1.0f-factt;
 -
 -                              if (mtex->blendtype==MTEX_BLEND) {
 -                                      shi->displace[0]= factt*shi->vn[0] + facmm*shi->displace[0];
 -                                      shi->displace[1]= factt*shi->vn[1] + facmm*shi->displace[1];
 -                                      shi->displace[2]= factt*shi->vn[2] + facmm*shi->displace[2];
 -                              }
 -                              else if (mtex->blendtype==MTEX_MUL) {
 -                                      shi->displace[0]*= factt*shi->vn[0];
 -                                      shi->displace[1]*= factt*shi->vn[1];
 -                                      shi->displace[2]*= factt*shi->vn[2];
 -                              }
 -                              else { /* add or sub */
 -                                      if (mtex->blendtype==MTEX_SUB) factt= -factt;
 -                                      shi->displace[0]+= factt*shi->vn[0];
 -                                      shi->displace[1]+= factt*shi->vn[1];
 -                                      shi->displace[2]+= factt*shi->vn[2];
 -                              }
 -                      }
 -
 -                      if (mtex->mapto & MAP_VARS) {
 -                              /* stencil maps on the texture control slider, not texture intensity value */
 -
 -                              if (rgbnor & TEX_RGB) {
 -                                      if (texres.talpha) texres.tin = texres.ta;
 -                                      else               texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
 -                              }
 -
 -                              if (mtex->mapto & MAP_REF) {
 -                                      float difffac= mtex->difffac*stencilTin;
 -
 -                                      shi->refl= texture_value_blend(mtex->def_var, shi->refl, texres.tin, difffac, mtex->blendtype);
 -                                      if (shi->refl<0.0f) shi->refl= 0.0f;
 -                              }
 -                              if (mtex->mapto & MAP_SPEC) {
 -                                      float specfac= mtex->specfac*stencilTin;
 -
 -                                      shi->spec= texture_value_blend(mtex->def_var, shi->spec, texres.tin, specfac, mtex->blendtype);
 -                                      if (shi->spec<0.0f) shi->spec= 0.0f;
 -                              }
 -                              if (mtex->mapto & MAP_EMIT) {
 -                                      float emitfac= mtex->emitfac*stencilTin;
 -
 -                                      shi->emit= texture_value_blend(mtex->def_var, shi->emit, texres.tin, emitfac, mtex->blendtype);
 -                                      if (shi->emit<0.0f) shi->emit= 0.0f;
 -                              }
 -                              if (mtex->mapto & MAP_ALPHA) {
 -                                      float alphafac= mtex->alphafac*stencilTin;
 -
 -                                      shi->alpha= texture_value_blend(mtex->def_var, shi->alpha, texres.tin, alphafac, mtex->blendtype);
 -                                      if (shi->alpha<0.0f) shi->alpha= 0.0f;
 -                                      else if (shi->alpha>1.0f) shi->alpha= 1.0f;
 -                              }
 -                              if (mtex->mapto & MAP_HAR) {
 -                                      float har;  /* have to map to 0-1 */
 -                                      float hardfac= mtex->hardfac*stencilTin;
 -
 -                                      har= ((float)shi->har)/128.0f;
 -                                      har= 128.0f*texture_value_blend(mtex->def_var, har, texres.tin, hardfac, mtex->blendtype);
 -
 -                                      if (har<1.0f) shi->har= 1;
 -                                      else if (har>511) shi->har= 511;
 -                                      else shi->har= (int)har;
 -                              }
 -                              if (mtex->mapto & MAP_RAYMIRR) {
 -                                      float raymirrfac= mtex->raymirrfac*stencilTin;
 -
 -                                      shi->ray_mirror= texture_value_blend(mtex->def_var, shi->ray_mirror, texres.tin, raymirrfac, mtex->blendtype);
 -                                      if (shi->ray_mirror<0.0f) shi->ray_mirror= 0.0f;
 -                                      else if (shi->ray_mirror>1.0f) shi->ray_mirror= 1.0f;
 -                              }
 -                              if (mtex->mapto & MAP_TRANSLU) {
 -                                      float translfac= mtex->translfac*stencilTin;
 -
 -                                      shi->translucency= texture_value_blend(mtex->def_var, shi->translucency, texres.tin, translfac, mtex->blendtype);
 -                                      if (shi->translucency<0.0f) shi->translucency= 0.0f;
 -                                      else if (shi->translucency>1.0f) shi->translucency= 1.0f;
 -                              }
 -                              if (mtex->mapto & MAP_AMB) {
 -                                      float ambfac= mtex->ambfac*stencilTin;
 -
 -                                      shi->amb= texture_value_blend(mtex->def_var, shi->amb, texres.tin, ambfac, mtex->blendtype);
 -                                      if (shi->amb<0.0f) shi->amb= 0.0f;
 -                                      else if (shi->amb>1.0f) shi->amb= 1.0f;
 -
 -                                      shi->ambr= shi->amb*re->wrld.ambr;
 -                                      shi->ambg= shi->amb*re->wrld.ambg;
 -                                      shi->ambb= shi->amb*re->wrld.ambb;
 -                              }
 -                      }
 -              }
 -      }
 -      if ((use_compat_bump || use_ntap_bump || found_nmapping) && (shi->mat->mode & MA_TANGENT_V) != 0) {
 -              const float fnegdot = -dot_v3v3(shi->vn, shi->tang);
 -              /* apply Gram-Schmidt projection */
 -              madd_v3_v3fl(shi->tang,  shi->vn, fnegdot);
 -              normalize_v3(shi->tang);
 -      }
 -}
 -
 -
 -void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_r[3], float *val, Render *re)
 -{
 -      const bool skip_load_image = (re->r.scemode & R_NO_IMAGE_LOAD) != 0;
 -      const bool texnode_preview = (re->r.scemode & R_TEXNODE_PREVIEW) != 0;
 -      MTex *mtex;
 -      Tex *tex;
 -      TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
 -      int tex_nr, rgbnor= 0;
 -      float co[3], texvec[3];
 -      float fact, stencilTin=1.0;
 -
 -      if (re->r.scemode & R_NO_TEX) return;
 -      /* here: test flag if there's a tex (todo) */
 -
 -      for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
 -              /* separate tex switching */
 -              if (shi->mat->septex & (1<<tex_nr)) continue;
 -
 -              if (shi->mat->mtex[tex_nr]) {
 -                      mtex= shi->mat->mtex[tex_nr];
 -                      tex= mtex->tex;
 -                      if (tex == NULL) continue;
 -
 -                      /* only process if this texture is mapped
 -                       * to one that we're interested in */
 -                      if (!(mtex->mapto & mapto_flag)) continue;
 -
 -                      /* which coords */
 -                      if (mtex->texco==TEXCO_OBJECT) {
 -                              Object *ob= mtex->object;
 -                              if (ob) {
 -                                      copy_v3_v3(co, xyz);
 -                                      if (mtex->texflag & MTEX_OB_DUPLI_ORIG) {
 -                                              if (shi->obi && shi->obi->duplitexmat)
 -                                                      mul_m4_v3(shi->obi->duplitexmat, co);
 -                                      }
 -                                      mul_m4_v3(ob->imat_ren, co);
 -
 -                                      if (mtex->texflag & MTEX_MAPTO_BOUNDS && ob->bb) {
 -                                              /* use bb vec[0] as min and bb vec[6] as max */
 -                                              co[0] = (co[0] - ob->bb->vec[0][0]) / (ob->bb->vec[6][0]-ob->bb->vec[0][0]) * 2.0f - 1.0f;
 -                                              co[1] = (co[1] - ob->bb->vec[0][1]) / (ob->bb->vec[6][1]-ob->bb->vec[0][1]) * 2.0f - 1.0f;
 -                                              co[2] = (co[2] - ob->bb->vec[0][2]) / (ob->bb->vec[6][2]-ob->bb->vec[0][2]) * 2.0f - 1.0f;
 -                                      }
 -                              }
 -                      }
 -                      /* not really orco, but 'local' */
 -                      else if (mtex->texco==TEXCO_ORCO) {
 -
 -                              if (mtex->texflag & MTEX_DUPLI_MAPTO) {
 -                                      copy_v3_v3(co, shi->duplilo);
 -                              }
 -                              else {
 -                                      Object *ob= shi->obi->ob;
 -                                      copy_v3_v3(co, xyz);
 -                                      mul_m4_v3(ob->imat_ren, co);
 -
 -                                      if (mtex->texflag & MTEX_MAPTO_BOUNDS && ob->bb) {
 -                                              /* use bb vec[0] as min and bb vec[6] as max */
 -                                              co[0] = (co[0] - ob->bb->vec[0][0]) / (ob->bb->vec[6][0]-ob->bb->vec[0][0]) * 2.0f - 1.0f;
 -                                              co[1] = (co[1] - ob->bb->vec[0][1]) / (ob->bb->vec[6][1]-ob->bb->vec[0][1]) * 2.0f - 1.0f;
 -                                              co[2] = (co[2] - ob->bb->vec[0][2]) / (ob->bb->vec[6][2]-ob->bb->vec[0][2]) * 2.0f - 1.0f;
 -                                      }
 -                              }
 -                      }
 -                      else if (mtex->texco==TEXCO_GLOB) {
 -                              copy_v3_v3(co, xyz);
 -                              mul_m4_v3(re->viewinv, co);
 -                      }
 -                      else {
 -                              continue;  /* can happen when texco defines disappear and it renders old files */
 -                      }
 -
 -                      texres.nor= NULL;
 -
 -                      if (tex->type == TEX_IMAGE) {
 -                              continue;  /* not supported yet */
 -                              //do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
 -                      }
 -                      else {
 -                              /* placement */
 -                              if (mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]);
 -                              else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
 -
 -                              if (mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]);
 -                              else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
 -
 -                              if (mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]);
 -                              else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
 -                      }
 -
 -                      rgbnor = multitex(tex,
 -                                        texvec,
 -                                        NULL, NULL,
 -                                        0,
 -                                        &texres,
 -                                        shi->thread,
 -                                        mtex->which_output,
 -                                        re->pool,
 -                                        skip_load_image,
 -                                        texnode_preview,
 -                                        true);        /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
 -
 -                      /* texture output */
 -
 -                      if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
 -                              texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
 -                              rgbnor -= TEX_RGB;
 -                      }
 -                      if (mtex->texflag & MTEX_NEGATIVE) {
 -                              if (rgbnor & TEX_RGB) {
 -                                      texres.tr= 1.0f-texres.tr;
 -                                      texres.tg= 1.0f-texres.tg;
 -                                      texres.tb= 1.0f-texres.tb;
 -                              }
 -                              texres.tin= 1.0f-texres.tin;
 -                      }
 -                      if (mtex->texflag & MTEX_STENCIL) {
 -                              if (rgbnor & TEX_RGB) {
 -                                      fact= texres.ta;
 -                                      texres.ta*= stencilTin;
 -                                      stencilTin*= fact;
 -                              }
 -                              else {
 -                                      fact= texres.tin;
 -                                      texres.tin*= stencilTin;
 -                                      stencilTin*= fact;
 -                              }
 -                      }
 -
 -
 -                      if ((mapto_flag & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL)) && (mtex->mapto & (MAP_EMISSION_COL+MAP_TRANSMISSION_COL+MAP_REFLECTION_COL))) {
 -                              float tcol[3];
 -
 -                              /* stencil maps on the texture control slider, not texture intensity value */
 -
 -                              if ((rgbnor & TEX_RGB) == 0) {
 -                                      copy_v3_v3(tcol, &mtex->r);
 -                              }
 -                              else if (mtex->mapto & MAP_DENSITY) {
 -                                      copy_v3_v3(tcol, &texres.tr);
 -                                      if (texres.talpha) {
 -                                              texres.tin = stencilTin;
 -                                      }
 -                              }
 -                              else {
 -                                      copy_v3_v3(tcol, &texres.tr);
 -                                      if (texres.talpha) {
 -                                              texres.tin= texres.ta;
 -                                      }
 -                              }
 -
 -                              /* used for emit */
 -                              if ((mapto_flag & MAP_EMISSION_COL) && (mtex->mapto & MAP_EMISSION_COL)) {
 -                                      float colemitfac= mtex->colemitfac*stencilTin;
 -                                      texture_rgb_blend(col_r, tcol, col_r, texres.tin, colemitfac, mtex->blendtype);
 -                              }
 -
 -                              if ((mapto_flag & MAP_REFLECTION_COL) && (mtex->mapto & MAP_REFLECTION_COL)) {
 -                                      float colreflfac= mtex->colreflfac*stencilTin;
 -                                      texture_rgb_blend(col_r, tcol, col_r, texres.tin, colreflfac, mtex->blendtype);
 -                              }
 -
 -                              if ((mapto_flag & MAP_TRANSMISSION_COL) && (mtex->mapto & MAP_TRANSMISSION_COL)) {
 -                                      float coltransfac= mtex->coltransfac*stencilTin;
 -                                      texture_rgb_blend(col_r, tcol, col_r, texres.tin, coltransfac, mtex->blendtype);
 -                              }
 -                      }
 -
 -                      if ((mapto_flag & MAP_VARS) && (mtex->mapto & MAP_VARS)) {
 -                              /* stencil maps on the texture control slider, not texture intensity value */
 -
 -                              /* convert RGB to intensity if intensity info isn't provided */
 -                              if (rgbnor & TEX_RGB) {
 -                                      if (texres.talpha)  texres.tin = texres.ta;
 -                                      else                texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
 -                              }
 -
 -                              if ((mapto_flag & MAP_EMISSION) && (mtex->mapto & MAP_EMISSION)) {
 -                                      float emitfac= mtex->emitfac*stencilTin;
 -
 -                                      *val = texture_value_blend(mtex->def_var, *val, texres.tin, emitfac, mtex->blendtype);
 -                                      if (*val<0.0f) *val= 0.0f;
 -                              }
 -                              if ((mapto_flag & MAP_DENSITY) && (mtex->mapto & MAP_DENSITY)) {
 -                                      float densfac= mtex->densfac*stencilTin;
 -
 -                                      *val = texture_value_blend(mtex->def_var, *val, texres.tin, densfac, mtex->blendtype);
 -                                      CLAMP(*val, 0.0f, 1.0f);
 -                              }
 -                              if ((mapto_flag & MAP_SCATTERING) && (mtex->mapto & MAP_SCATTERING)) {
 -                                      float scatterfac= mtex->scatterfac*stencilTin;
 -
 -                                      *val = texture_value_blend(mtex->def_var, *val, texres.tin, scatterfac, mtex->blendtype);
 -                                      CLAMP(*val, 0.0f, 1.0f);
 -                              }
 -                              if ((mapto_flag & MAP_REFLECTION) && (mtex->mapto & MAP_REFLECTION)) {
 -                                      float reflfac= mtex->reflfac*stencilTin;
 -
 -                                      *val = texture_value_blend(mtex->def_var, *val, texres.tin, reflfac, mtex->blendtype);
 -                                      CLAMP(*val, 0.0f, 1.0f);
 -                              }
 -                      }
 -              }
 -      }
 -}
 -
 -
 -/* ------------------------------------------------------------------------- */
 -
 -void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
 -{
 -      const bool skip_load_image = har->skip_load_image;
 -      const bool texnode_preview = har->texnode_preview;
 -      MTex *mtex;
 -      TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
 -      float texvec[3], dxt[3], dyt[3], fact, facm, dx;
 -      int rgb, osatex;
 -
 -      if (R.r.scemode & R_NO_TEX) return;
 -
 -      mtex= har->mat->mtex[0];
 -      if (har->mat->septex & (1<<0)) return;
 -      if (mtex->tex==NULL) return;
 -
 -      /* no normal mapping */
 -      texres.nor= NULL;
 -
 -      texvec[0]= xn/har->rad;
 -      texvec[1]= yn/har->rad;
 -      texvec[2]= 0.0;
 -
 -      osatex= (har->mat->texco & TEXCO_OSA);
 -
 -      /* placement */
 -      if (mtex->projx) texvec[0]= mtex->size[0]*(texvec[mtex->projx-1]+mtex->ofs[0]);
 -      else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
 -
 -      if (mtex->projy) texvec[1]= mtex->size[1]*(texvec[mtex->projy-1]+mtex->ofs[1]);
 -      else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
 -
 -      if (mtex->projz) texvec[2]= mtex->size[2]*(texvec[mtex->projz-1]+mtex->ofs[2]);
 -      else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
 -
 -      if (osatex) {
 -
 -              dx= 1.0f/har->rad;
 -
 -              if (mtex->projx) {
 -                      dxt[0]= mtex->size[0]*dx;
 -                      dyt[0]= mtex->size[0]*dx;
 -              }
 -              else dxt[0]= dyt[0]= 0.0;
 -
 -              if (mtex->projy) {
 -                      dxt[1]= mtex->size[1]*dx;
 -                      dyt[1]= mtex->size[1]*dx;
 -              }
 -              else dxt[1]= dyt[1]= 0.0;
 -
 -              if (mtex->projz) {
 -                      dxt[2]= 0.0;
 -                      dyt[2]= 0.0;
 -              }
 -              else dxt[2]= dyt[2]= 0.0;
 -
 -      }
 -
 -      if (mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
 -
 -      rgb = multitex(mtex->tex,
 -                     texvec,
 -                     dxt, dyt,
 -                     osatex,
 -                     &texres,
 -                     0,
 -                     mtex->which_output,
 -                     har->pool,
 -                     skip_load_image,
 -                     texnode_preview,
 -                     true);
 -
 -      /* texture output */
 -      if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
 -              texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
 -              rgb= 0;
 -      }
 -      if (mtex->texflag & MTEX_NEGATIVE) {
 -              if (rgb) {
 -                      texres.tr= 1.0f-texres.tr;
 -                      texres.tg= 1.0f-texres.tg;
 -                      texres.tb= 1.0f-texres.tb;
 -              }
 -              else texres.tin= 1.0f-texres.tin;
 -      }
 -
 -      /* mapping */
 -      if (mtex->mapto & MAP_COL) {
 -
 -              if (rgb==0) {
 -                      texres.tr= mtex->r;
 -                      texres.tg= mtex->g;
 -                      texres.tb= mtex->b;
 -              }
 -              else if (mtex->mapto & MAP_ALPHA) {
 -                      texres.tin= 1.0;
 -              }
 -              else texres.tin= texres.ta;
 -
 -              /* inverse gamma correction */
 -              if (mtex->tex->type==TEX_IMAGE) {
 -                      Image *ima = mtex->tex->ima;
 -                      ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &mtex->tex->iuser, har->pool);
 -
 -                      /* don't linearize float buffers, assumed to be linear */
 -                      if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
 -                              IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace);
 -
 -                      BKE_image_pool_release_ibuf(ima, ibuf, har->pool);
 -              }
 -
 -              fact= texres.tin*mtex->colfac;
 -              facm= 1.0f-fact;
 -
 -              if (mtex->blendtype==MTEX_MUL) {
 -                      facm= 1.0f-mtex->colfac;
 -              }
 -
 -              if (mtex->blendtype==MTEX_SUB) fact= -fact;
 -
 -              if (mtex->blendtype==MTEX_BLEND) {
 -                      col_r[0]= (fact*texres.tr + facm*har->r);
 -                      col_r[1]= (fact*texres.tg + facm*har->g);
 -                      col_r[2]= (fact*texres.tb + facm*har->b);
 -              }
 -              else if (mtex->blendtype==MTEX_MUL) {
 -                      col_r[0]= (facm+fact*texres.tr)*har->r;
 -                      col_r[1]= (facm+fact*texres.tg)*har->g;
 -                      col_r[2]= (facm+fact*texres.tb)*har->b;
 -              }
 -              else {
 -                      col_r[0]= (fact*texres.tr + har->r);
 -                      col_r[1]= (fact*texres.tg + har->g);
 -                      col_r[2]= (fact*texres.tb + har->b);
 -
 -                      CLAMP(col_r[0], 0.0f, 1.0f);
 -                      CLAMP(col_r[1], 0.0f, 1.0f);
 -                      CLAMP(col_r[2], 0.0f, 1.0f);
 -              }
 -      }
 -      if (mtex->mapto & MAP_ALPHA) {
 -              if (rgb) {
 -                      if (texres.talpha) {
 -                              texres.tin = texres.ta;
 -                      }
 -                      else {
 -                              texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
 -                      }
 -              }
 -
 -              col_r[3]*= texres.tin;
 -      }
 -}
 -
 -/* ------------------------------------------------------------------------- */
 -
 -/* hor and zen are RGB vectors, blend is 1 float, should all be initialized */
 -void do_sky_tex(
 -        const float rco[3], const float view[3], const float lo[3], const float dxyview[2],
 -        float hor[3], float zen[3], float *blend, int skyflag, short thread)
 -{
 -      const bool skip_load_image = (R.r.scemode & R_NO_IMAGE_LOAD) != 0;
 -      const bool texnode_preview = (R.r.scemode & R_TEXNODE_PREVIEW) != 0;
 -      MTex *mtex;
 -      Tex *tex;
 -      TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
 -      float fact, stencilTin=1.0;
 -      float tempvec[3], texvec[3], dxt[3], dyt[3];
 -      int tex_nr, rgb= 0;
 -
 -      if (R.r.scemode & R_NO_TEX) return;
 -      /* todo: add flag to test if there's a tex */
 -      texres.nor= NULL;
 -
 -      for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
 -              if (R.wrld.mtex[tex_nr]) {
 -                      const float *co;
 -
 -                      mtex= R.wrld.mtex[tex_nr];
 -
 -                      tex= mtex->tex;
 -                      if (tex == NULL) continue;
 -                      /* if (mtex->mapto==0) continue; */
 -
 -                      /* which coords */
 -                      co= lo;
 -
 -                      /* dxt dyt just from 1 value */
 -                      if (dxyview) {
 -                              dxt[0]= dxt[1]= dxt[2]= dxyview[0];
 -                              dyt[0]= dyt[1]= dyt[2]= dxyview[1];
 -                      }
 -                      else {
 -                              dxt[0]= dxt[1]= dxt[2]= 0.0;
 -                              dyt[0]= dyt[1]= dyt[2]= 0.0;
 -                      }
 -
 -                      /* Grab the mapping settings for this texture */
 -                      switch (mtex->texco) {
 -                      case TEXCO_ANGMAP:
 -                              /* only works with texture being "real" */
 -                              /* use saacos(), fixes bug [#22398], float precision caused lo[2] to be slightly less than -1.0 */
 -                              if (lo[0] || lo[1]) { /* check for zero case [#24807] */
 -                                      fact= (1.0f/(float)M_PI)*saacos(lo[2])/(sqrtf(lo[0]*lo[0] + lo[1]*lo[1]));
 -                                      tempvec[0]= lo[0]*fact;
 -                                      tempvec[1]= lo[1]*fact;
 -                                      tempvec[2]= 0.0;
 -                              }
 -                              else {
 -                                      /* this value has no angle, the vector is directly along the view.
 -                                       * avoid divide by zero and use a dummy value. */
 -                                      tempvec[0]= 1.0f;
 -                                      tempvec[1]= 0.0;
 -                                      tempvec[2]= 0.0;
 -                              }
 -                              co= tempvec;
 -                              break;
 -
 -                      case TEXCO_H_SPHEREMAP:
 -                      case TEXCO_H_TUBEMAP:
 -                              if (skyflag & WO_ZENUP) {
 -                                      if (mtex->texco==TEXCO_H_TUBEMAP) map_to_tube( tempvec, tempvec+1, lo[0], lo[2], lo[1]);
 -                                      else map_to_sphere(tempvec, tempvec+1, lo[0], lo[2], lo[1]);
 -                                      /* tube/spheremap maps for outside view, not inside */
 -                                      tempvec[0]= 1.0f-tempvec[0];
 -                                      /* only top half */
 -                                      tempvec[1]= 2.0f*tempvec[1]-1.0f;
 -                                      tempvec[2]= 0.0;
 -                                      /* and correction for do_2d_mapping */
 -                                      tempvec[0]= 2.0f*tempvec[0]-1.0f;
 -                                      tempvec[1]= 2.0f*tempvec[1]-1.0f;
 -                                      co= tempvec;
 -                              }
 -                              else {
 -                                      /* potentially dangerous... check with multitex! */
 -                                      continue;
 -                              }
 -                              break;
 -                      case TEXCO_EQUIRECTMAP:
 -                              tempvec[0]= -atan2f(lo[2], lo[0]) / (float)M_PI;
 -                              tempvec[1]=  atan2f(lo[1], hypot(lo[0], lo[2])) / (float)M_PI_2;
 -                              tempvec[2]= 0.0f;
 -                              co= tempvec;
 -                              break;
 -                      case TEXCO_OBJECT:
 -                              if (mtex->object) {
 -                                      copy_v3_v3(tempvec, lo);
 -                                      mul_m4_v3(mtex->object->imat_ren, tempvec);
 -                                      co= tempvec;
 -                              }
 -                              break;
 -
 -                      case TEXCO_GLOB:
 -                              if (rco) {
 -                                      copy_v3_v3(tempvec, rco);
 -                                      mul_m4_v3(R.viewinv, tempvec);
 -                                      co= tempvec;
 -                              }
 -                              else
 -                                      co= lo;
 -
 -//                            copy_v3_v3(shi->dxgl, shi->dxco);
 -//                            mul_m3_v3(R.imat, shi->dxco);
 -//                            copy_v3_v3(shi->dygl, shi->dyco);
 -//                            mul_m3_v3(R.imat, shi->dyco);
 -                              break;
 -                      case TEXCO_VIEW:
 -                              co = view;
 -                              break;
 -                      }
 -
 -                      /* placement */
 -                      if (mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]);
 -                      else texvec[0]= mtex->size[0]*(mtex->ofs[0]);
 -
 -                      if (mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]);
 -                      else texvec[1]= mtex->size[1]*(mtex->ofs[1]);
 -
 -                      if (mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]);
 -                      else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
 -
 -                      /* texture */
 -                      if (tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
 -
 -                      rgb = multitex(mtex->tex,
 -                                     texvec,
 -                                     dxt, dyt,
 -                                     R.osa,
 -                                     &texres,
 -                                     thread,
 -                                     mtex->which_output,
 -                                     R.pool,
 -                                     skip_load_image,
 -                                     texnode_preview,
 -                                     true);
 -
 -                      /* texture output */
 -                      if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
 -                              texres.tin = IMB_colormanagement_get_luminance(&texres.tr);
 -                              rgb= 0;
 -                      }
 -                      if (mtex->texflag & MTEX_NEGATIVE) {
 -                              if (rgb) {
 -                                      texres.tr= 1.0f-texres.tr;
 -                                      texres.tg= 1.0f-texres.tg;
 -                                      texres.tb= 1.0f-texres.tb;
 -                              }
 -                              else texres.tin= 1.0f-texres.tin;
 -                      }
 -                      if (mtex->texflag & MTEX_STENCIL) {
 -                              if (rgb) {
 -                                      fact= texres.ta;
 -                                      texres.ta*= stencilTin;
 -                                      stencilTin*= fact;
 -                              }
 -                              else {
 -                                      fact= texres.tin;
 -                                      texres.tin*= stencilTin;
 -                                      stencilTin*= fact;
 -                              }
 -              &