Orange branch feature; Material Layering
authorTon Roosendaal <ton@blender.org>
Sun, 4 Dec 2005 14:32:21 +0000 (14:32 +0000)
committerTon Roosendaal <ton@blender.org>
Sun, 4 Dec 2005 14:32:21 +0000 (14:32 +0000)
(WIP, don't bugs for this in tracker yet please!)

- New Panel "Layers" in Material buttons, allows to add unlimited amount
  of materials on top of each other.
- Every Layer is actually just another Material, which gets rendered/shaded
  (including texture), and then added on top of previous layer with an
  operation like Mix, Add, Mult, etc.
- Layers render fully independent, so bumpmaps are not passed on to next
  layers.
- Per Layer you can set if it influences Diffuse, Specular or Alpha
- If a Material returns alpha (like from texture), the alpha value is
  used for adding the layers too.
- New texture "Map To" channel allows to have a texture work on a Layer
- Each layer, including basis Material, can be turned on/off individually

Notes:

- at this moment, the full shading pass happens for each layer, including
  shadow, AO and raytraced mirror or transparency...
- I had to remove old hacks from preview render, which corrected reflected
  normals for preview texturing.
- still needs loadsa testing!

23 files changed:
source/blender/blenkernel/BKE_bad_level_calls.h
source/blender/blenkernel/BKE_material.h
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/material.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/butspace.h
source/blender/makesdna/DNA_material_types.h
source/blender/render/extern/include/render.h
source/blender/render/extern/include/render_types.h
source/blender/render/intern/include/rendercore.h
source/blender/render/intern/source/initrender.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/texture.c
source/blender/renderconverter/intern/convertBlenderScene.c
source/blender/src/buttons_shading.c
source/blender/src/drawview.c
source/blender/src/editobject.c
source/blender/src/header_buttonswin.c
source/blender/src/headerbuttons.c
source/blender/src/interface_panel.c
source/blender/src/previewrender.c

index 905b6d3bf74c9f5840349744741eaaf8dd47a035..a8d9693f62f118dd00ada5648dd7415a9b66a081 100644 (file)
@@ -158,7 +158,6 @@ void do_material_tex(ShadeInput *shi);
 void externtex(struct MTex *mtex, float *vec, float *tin, float *tr, 
        float *tg, float *tb, float *ta);
 void init_render_textures(void);
-void end_render_textures(void);
 
 void RE_free_envmap(struct EnvMap *env);      
 void RE_free_envmapdata(struct EnvMap *env);
index fcdbed10ffa6b83b287066044cfaee2b95fcc981..16a320010eca9b76d603de62c7bd6a1fd71d0e53 100644 (file)
@@ -48,16 +48,18 @@ void init_material(struct Material *ma);
 struct Material *add_material(char *name);
 struct Material *copy_material(struct Material *ma);
 void make_local_material(struct Material *ma);
+
 struct Material ***give_matarar(struct Object *ob);
 short *give_totcolp(struct Object *ob);
 struct Material *give_current_material(struct Object *ob, int act);
 ID *material_from(struct Object *ob, int act);
 void assign_material(struct Object *ob, struct Material *ma, int act);
 void new_material_to_objectdata(struct Object *ob);
+
+struct Material *get_active_matlayer(struct Material *ma);
 void init_render_material(struct Material *ma);
 void init_render_materials(void);
-void end_render_material(struct Material *ma);
-void end_render_materials(void);
+
 void automatname(struct Material *ma);
 void delete_material_index(void);            
 
index 457c6a2d7e58a0b43ee0d054dd6112a60abf8122..778cb71f99a6592c6a03efb41f758fc21f9477a4 100644 (file)
@@ -206,8 +206,6 @@ int BPY_call_importloader(char *name)
 
 void do_material_tex(ShadeInput *shi){}
 void externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta){}
-void init_render_textures(void){}
-void end_render_textures(void){}
 
 void    RE_free_envmap(struct EnvMap *env){}      
 struct EnvMap *RE_copy_envmap(struct EnvMap *env){ return env;}
index 9273bd8eb712a43ce01b115fa4904003db85d8b2..b143def9f322b2c41429b290e1b9f46b8b745bfe 100644 (file)
@@ -726,15 +726,6 @@ static void init_fastshade_for_ob(Object *ob, int *need_orco_r, float mat[4][4],
                }
        }
 }
-static void end_fastshade_for_ob(Object *ob)
-{
-       int a;
-
-       for(a=0; a<ob->totcol; a++) {
-               Material *ma= give_current_material(ob, a+1);
-               if(ma) end_render_material(ma);
-       }
-}
 
 void mesh_create_shadedColors(Object *ob, int onlyForMesh, unsigned int **col1_r, unsigned int **col2_r)
 {
@@ -846,7 +837,6 @@ void mesh_create_shadedColors(Object *ob, int onlyForMesh, unsigned int **col1_r
 
        if (dmNeedsFree) dm->release(dm);
 
-       end_fastshade_for_ob(ob);
 }
 
 void shadeDispList(Object *ob)
@@ -986,8 +976,6 @@ void shadeDispList(Object *ob)
                        dl= dl->next;
                }
        }
-       
-       end_fastshade_for_ob(ob);
 }
 
 void reshadeall_displist(void)
@@ -1999,8 +1987,6 @@ void imagestodisplist(void)
                base= base->next;
        }
        
-       end_render_textures();
-       
        allqueue(REDRAWVIEW3D, 0);
 }
 
index d303a7ed5bd59c250778937d1db6db2ff480131e..ef5a29020d4f7b99e3b44eca82e7c929e057dd61 100644 (file)
 #include <string.h>
 #include "MEM_guardedalloc.h"
 
+#include "DNA_curve_types.h"
 #include "DNA_material_types.h"
-#include "DNA_texture_types.h"
 #include "DNA_mesh_types.h"
-#include "DNA_object_types.h"
-#include "DNA_curve_types.h"
 #include "DNA_meta_types.h"
+#include "DNA_object_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
 
 #include "BLI_blenlib.h"
 
 #include "BKE_bad_level_calls.h"
-#include "BKE_utildefines.h"
-
+#include "BKE_blender.h"
+#include "BKE_displist.h"
 #include "BKE_global.h"
-#include "BKE_main.h"
-
-#include "BKE_mesh.h"
 #include "BKE_library.h"
-#include "BKE_displist.h"
+#include "BKE_main.h"
 #include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_utildefines.h"
 
 #include "BPY_extern.h"
 
+/* not material itself */
 void free_material(Material *ma)
 {
-       int a;
+       MaterialLayer *ml;
        MTex *mtex;
+       int a;
 
        BPY_free_scriptlink(&ma->scriptlink);
        
@@ -74,6 +75,11 @@ void free_material(Material *ma)
        
        if(ma->ramp_col) MEM_freeN(ma->ramp_col);
        if(ma->ramp_spec) MEM_freeN(ma->ramp_spec);
+       
+       for(ml= ma->layers.first; ml; ml= ml->next)
+               if(ml->mat) ml->mat->id.us--;
+       
+       BLI_freelistN(&ma->layers);
 }
 
 void init_material(Material *ma)
@@ -115,8 +121,9 @@ void init_material(Material *ma)
        
        ma->rampfac_col= 1.0;
        ma->rampfac_spec= 1.0;
-       ma->pr_lamp= 3; // two lamps, is bits
-       
+       ma->pr_lamp= 3;                 /* two lamps, is bits */
+       ma->ml_flag= ML_RENDER; /* default render base material for layers */
+
        ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RADIO|MA_TANGENT_STR;
 }
 
@@ -134,6 +141,7 @@ Material *add_material(char *name)
 Material *copy_material(Material *ma)
 {
        Material *man;
+       MaterialLayer *ml;
        int a;
        
        man= copy_libblock(ma);
@@ -149,9 +157,14 @@ Material *copy_material(Material *ma)
        }
        
        BPY_copy_scriptlink(&ma->scriptlink);
+       
        if(ma->ramp_col) man->ramp_col= MEM_dupallocN(ma->ramp_col);
        if(ma->ramp_spec) man->ramp_spec= MEM_dupallocN(ma->ramp_spec);
        
+       duplicatelist(&man->layers, &ma->layers);
+       for(ml= man->layers.first; ml; ml= ml->next)
+               id_us_plus((ID *)ml->mat);
+
        return man;
 }
 
@@ -245,9 +258,25 @@ void make_local_material(Material *ma)
                new_id(0, (ID *)ma, 0);
        }
        else if(local && lib) {
+               Material *mat;
+               MaterialLayer *ml;
+               
                man= copy_material(ma);
                man->id.us= 0;
                
+               /* do material layers */
+               for(mat= G.main->mat.first; mat; mat= mat->id.next) {
+                       if(mat->id.lib==NULL) {
+                               for(ml= mat->layers.first; ml; ml= ml->next) {
+                                       if(ml->mat==ma) {
+                                               ml->mat= man;
+                                               man->id.us++;
+                                               ma->id.us--;
+                                       }
+                               }
+                       }
+               }
+               
                /* do objects */
                ob= G.main->object.first;
                while(ob) {
@@ -534,6 +563,18 @@ void new_material_to_objectdata(Object *ob)
        ob->actcol= ob->totcol;
 }
 
+Material *get_active_matlayer(Material *ma)
+{
+       MaterialLayer *ml;
+       
+       if(ma==NULL) return NULL;
+       
+       for(ml= ma->layers.first; ml; ml= ml->next)
+               if(ml->flag & ML_ACTIVE) break;
+       if(ml)
+               return ml->mat;
+       return ma;
+}
 
 void init_render_material(Material *ma)
 {
@@ -586,43 +627,30 @@ void init_render_material(Material *ma)
        ma->ambg= ma->amb*R.wrld.ambg;
        ma->ambb= ma->amb*R.wrld.ambb;
        
+       /* will become or-ed result of all layer modes */
+       ma->mode_l= ma->mode;
 }
 
 void init_render_materials()
 {
        Material *ma;
+       MaterialLayer *ml;
        
-       ma= G.main->mat.first;
-       while(ma) {
+       /* two steps, first initialize, then or the flags for layers */
+       for(ma= G.main->mat.first; ma; ma= ma->id.next) {
                if(ma->id.us) init_render_material(ma);
-               ma= ma->id.next;
        }
        
-}
-
-void end_render_material(Material *ma)
-{
-       /* XXXX obsolete? check! */
-       if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) {
-               if( !(ma->mode & MA_HALO) ) {
-                       ma->r= ma->g= ma->b= 1.0;
+       for(ma= G.main->mat.first; ma; ma= ma->id.next) {
+               for(ml= ma->layers.first; ml; ml= ml->next) {
+                       if(ml->mat) {
+                               ma->texco |= ml->mat->texco;
+                               ma->mode_l |= ml->mat->mode;
+                       }
                }
-       }
-}
-
-void end_render_materials()
-{
-       Material *ma;
-       
-       ma= G.main->mat.first;
-       while(ma) {
-               if(ma->id.us) end_render_material(ma);
-               ma= ma->id.next;
-       }
-       
+       }       
 }
 
-
 /* ****************** */
 
 char colname_array[125][20]= {
index 1fb001636444c91f476e3f3480bc08b295b61b62..5207c79b0cad3765d7ef1d7db92fdecc3452f10a 100644 (file)
@@ -1,19 +1,12 @@
 /*
- * readfile.c
- *
- * .blend file reading
- *
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -31,7 +24,7 @@
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  *
  */
 
@@ -1983,6 +1976,7 @@ static void direct_link_texture(FileData *fd, Tex *tex)
 static void lib_link_material(FileData *fd, Main *main)
 {
        Material *ma;
+       MaterialLayer *ml;
        MTex *mtex;
        int a;
 
@@ -2000,6 +1994,10 @@ static void lib_link_material(FileData *fd, Main *main)
                                }
                        }
                        lib_link_scriptlink(fd, &ma->id, &ma->scriptlink);
+                       
+                       for (ml=ma->layers.first; ml; ml=ml->next)
+                               ml->mat= newlibadr_us(fd, ma->id.lib, ml->mat);
+                               
                        ma->id.flag -= LIB_NEEDLINK;
                }
                ma= ma->id.next;
@@ -2010,8 +2008,6 @@ static void direct_link_material(FileData *fd, Material *ma)
 {
        int a;
 
-       direct_link_scriptlink(fd, &ma->scriptlink);
-
        for(a=0; a<MAX_MTEX; a++) {
                ma->mtex[a]= newdataadr(fd, ma->mtex[a]);
        }
@@ -2019,6 +2015,10 @@ static void direct_link_material(FileData *fd, Material *ma)
        ma->ramp_col= newdataadr(fd, ma->ramp_col);
        ma->ramp_spec= newdataadr(fd, ma->ramp_spec);
        
+       direct_link_scriptlink(fd, &ma->scriptlink);
+       
+       link_list(fd, &ma->layers);
+
 }
 
 /* ************ READ MESH ***************** */
@@ -5082,6 +5082,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                if(ma->mode & MA_TRACEBLE) ma->mode |= MA_SHADBUF;
                                ma->pad= 1;
                        }
+                       /* orange stuff, so should be done for 2.40 too */
+                       if(ma->layers.first==NULL) {
+                               ma->ml_flag= ML_RENDER;
+                       }
                }
        }
        
@@ -5301,6 +5305,7 @@ static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
 
 static void expand_material(FileData *fd, Main *mainvar, Material *ma)
 {
+       MaterialLayer *ml;
        int a;
 
        for(a=0; a<MAX_MTEX; a++) {
@@ -5309,7 +5314,13 @@ static void expand_material(FileData *fd, Main *mainvar, Material *ma)
                        expand_doit(fd, mainvar, ma->mtex[a]->object);
                }
        }
+       
        expand_doit(fd, mainvar, ma->ipo);
+       
+       for (ml=ma->layers.first; ml; ml=ml->next) {
+               if(ml->mat)
+                       expand_doit(fd, mainvar, ml->mat);
+       }
 }
 
 static void expand_lamp(FileData *fd, Main *mainvar, Lamp *la)
index f941b5f77d2d0b12f51ef2b884d2769e0c9cea31..0fd394428e352d1785adaa077b4fe2abbd20dd2a 100644 (file)
@@ -994,6 +994,7 @@ static void write_textures(WriteData *wd, ListBase *idbase)
 static void write_materials(WriteData *wd, ListBase *idbase)
 {
        Material *ma;
+       MaterialLayer *ml;
        int a;
 
        ma= idbase->first;
@@ -1010,6 +1011,10 @@ static void write_materials(WriteData *wd, ListBase *idbase)
                        if(ma->ramp_spec) writestruct(wd, DATA, "ColorBand", 1, ma->ramp_spec);
                        
                        write_scriptlink(wd, &ma->scriptlink);
+                       
+                       for (ml=ma->layers.first; ml; ml=ml->next)
+                               writestruct(wd, DATA, "MaterialLayer", 1, ml);
+
                }
                ma= ma->id.next;
        }
index e354b4b74d4d277f6661907793b0dfc90aa2babd..e62eb268ed995e8cee3be98b52cc7b128842cfe8 100644 (file)
@@ -180,6 +180,7 @@ void test_idbutton_cb(void *namev, void *arg2_unused);
 /* yafray: material preset menu event */
 #define B_MAT_YF_PRESET        1217
 
+#define B_MAT_LAYERBROWSE      1218
 
 /* *********************** */
 #define B_TEXBUTS              1400
index 5ef327502e1491ff1afaa534f5b82838946265c4..395c438c6e3c28a60095141dcde99745219bb0fe 100644 (file)
 #ifndef DNA_MATERIAL_TYPES_H
 #define DNA_MATERIAL_TYPES_H
 
-/*  #include "BLI_listBase.h" */
-
 #include "DNA_ID.h"
 #include "DNA_scriptlink_types.h"
+#include "DNA_listBase.h"
 
 #ifndef MAX_MTEX
 #define MAX_MTEX       10
@@ -48,20 +47,32 @@ struct Ipo;
 struct Material;
 struct ColorBand;
 
+typedef struct MaterialLayer {
+       struct MaterialLayer *next, *prev;
+       
+       struct Material *mat;
+       float blendfac;
+       short flag, blendmethod, menunr, pad;
+       int pad2;
+       
+} MaterialLayer;
+
 /* WATCH IT: change type? also make changes in ipo.h  */
 
 typedef struct Material {
        ID id;
        
        short colormodel, lay;          /* lay: for dynamics (old engine, until 2.04) */
+       /* note, keep this below synced with render_types.h */
        float r, g, b;
        float specr, specg, specb;
        float mirr, mirg, mirb;
        float ambr, ambb, ambg;
-       
        float amb, emit, ang, spectra, ray_mirror;
        float alpha, ref, spec, zoffs, add;
        float translucency;
+       /* end synced with render_types.h */
+       
        float fresnel_mir, fresnel_mir_i;
        float fresnel_tra, fresnel_tra_i;
        float filter;           /* filter added, for raytrace transparency */
@@ -69,16 +80,15 @@ typedef struct Material {
        short har;
        char seed1, seed2;
        
-       int mode; 
-       int mode2; /* even more material settings :) */
+       int mode, mode_l;               /* mode_l is the or-ed result of all layer modes */
        short flarec, starc, linec, ringc;
        float hasize, flaresize, subsize, flareboost;
        float strand_sta, strand_end, strand_ease;
+       float pad1;
        
        /* for buttons and render*/
        char rgbsel, texact, pr_type, pad;
-       short pr_back, pr_lamp, septex, pad4;
-       int pad5;
+       short pr_back, pr_lamp, septex, ml_flag;        /* ml_flag is for disable base material */
        
        /* shaders */
        short diff_shader, spec_shader;
@@ -97,6 +107,7 @@ typedef struct Material {
        float rampfac_col, rampfac_spec;
 
        struct MTex *mtex[10];
+       ListBase layers;
        struct Ipo *ipo;
        
        /* dynamic properties */
@@ -107,7 +118,7 @@ typedef struct Material {
        /* yafray: absorption color, dispersion parameters and material preset menu */
        float YF_ar, YF_ag, YF_ab, YF_dscale, YF_dpwr;
        int YF_dsmp, YF_preset, YF_djit;
-
+       
        ScriptLink scriptlink;
 } Material;
 
@@ -161,7 +172,7 @@ typedef struct Material {
 #define MA_DIFF_LAMBERT                0
 #define MA_DIFF_ORENNAYAR      1
 #define MA_DIFF_TOON           2
-#define MA_DIFF_MINNAERT        3
+#define MA_DIFF_MINNAERT    3
 
 /* spec_shader */
 #define MA_SPEC_COOKTORR       0
@@ -224,6 +235,7 @@ typedef struct Material {
 #define MAP_AMB                        2048
 #define MAP_DISPLACE   4096
 #define MAP_WARP               8192
+#define MAP_LAYER              16384
 
 /* pr_type */
 #define MA_FLAT                        0
@@ -233,5 +245,13 @@ typedef struct Material {
 /* pr_back */
 #define MA_DARK                        1
 
+/* MaterialLayer flag */
+#define ML_ACTIVE              1
+#define ML_RENDER              2
+#define ML_NEG_NORMAL  4
+#define ML_DIFFUSE             8
+#define ML_SPECULAR            16
+#define ML_ALPHA               32
+
 #endif
 
index e3eb926192c27970f146c0a4b4e8471e7ab9b836..abde461a9355478366ff2a5bd58902425f592c6c 100644 (file)
@@ -148,9 +148,7 @@ struct MTex;
 struct Tex;
 
 void init_render_textures(void);
-void end_render_textures(void);
 void init_render_texture(struct Tex *tex);
-void end_render_texture(struct Tex *tex);
 
 void do_material_tex(ShadeInput *shi);
 void do_lamp_tex(struct LampRen *la, float *lavec, ShadeInput *shi, float *fcol);
@@ -162,7 +160,6 @@ void externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg,
 /* envmap (4)                                                                   */
 /* ------------------------------------------------------------------------- */
 struct EnvMap;
-struct Tex;
 
 void    RE_free_envmapdata(struct EnvMap *env);
 void    RE_free_envmap(struct EnvMap *env);
@@ -173,6 +170,9 @@ struct EnvMap *RE_copy_envmap(struct EnvMap *env);
 /* --------------------------------------------------------------------- */
 /* rendercore (12)                                                        */
 /* --------------------------------------------------------------------- */
+struct MaterialLayer;
+struct ShadeResult;
+
 float Phong_Spec(float *n, float *l, float *v, int hard, int tangent);
 float CookTorr_Spec(float *n, float *l, float *v, int hard, int tangent);
 float Blinn_Spec(float *n, float *l, float *v, float refrac, float spec_power, int tangent);
@@ -188,6 +188,7 @@ void ramp_diffuse_result(float *diff, ShadeInput *shi);
 void do_specular_ramp(ShadeInput *shi, float is, float t, float *spec);
 void ramp_spec_result(float *specr, float *specg, float *specb, ShadeInput *shi);
 
+void matlayer_blend(struct MaterialLayer *ml, float blendfac, struct ShadeResult *target, struct ShadeResult *src);
 
 /* --------------------------------------------------------------------- */
 /* ray.c (2)                                                        */
index 8118e72f24ab4fe26e85d61e5a8877e95ad9b10c..ea3463f96aeaba49dbcc85527f9a082c31aa3735 100644 (file)
@@ -1,15 +1,12 @@
 /**
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,7 +24,7 @@
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 #ifndef RENDER_TYPES_H
@@ -58,6 +55,15 @@ typedef struct TexResult {
        float *nor;
 } TexResult;
 
+/* localized shade result data */
+typedef struct ShadeResult 
+{
+       float diff[3];
+       float spec[3];
+       float alpha;
+       
+} ShadeResult;
+
 /* localized renderloop data */
 typedef struct ShadeInput
 {
@@ -79,10 +85,11 @@ typedef struct ShadeInput
        
        /* individual copies: */
        int har;
+       float layerfac;
        
        /* texture coordinates */
        float lo[3], gl[3], uv[3], ref[3], orn[3], winco[3], sticky[3], vcol[3], rad[3];
-       float vn[3], facenor[3], view[3], refcol[4], displace[3], strand, tang[3];
+       float vn[3], vno[3], facenor[3], view[3], refcol[4], displace[3], strand, tang[3];
        
        /* dx/dy OSA coordinates */
        float dxco[3], dyco[3];
index 0859620982c485b2030e3fe37159de737edfacc5..8f236c502f44f5e0d111e30ed13b21bdf334594f 100644 (file)
 struct HaloRen;
 struct ShadeInput;
 
-typedef struct ShadeResult 
-{
-       float diff[3];
-       float spec[3];
-       float alpha;
-
-} ShadeResult;
-
 typedef struct PixStr
 {
        struct PixStr *next;
index 84eb9d9dfca5ac30bf021647b6ed01d1b6d0d3de..54cfc1742e88375a60fb6611e5ab3edb22ebd054 100644 (file)
@@ -536,7 +536,6 @@ void RE_free_render_data()
        R.rectz= NULL;
        R.rectspare= NULL;
        
-       end_render_material(&defmaterial);
        free_filt_mask();
 }
 
index b1ee0908eef2d0b252c8511889982cb5d49ebcd7..28eca24856e15f84f116b2db55f8e816fb591be8 100644 (file)
@@ -1107,65 +1107,84 @@ void shade_color(ShadeInput *shi, ShadeResult *shr)
        shr->alpha= shi->alpha;
 }
 
-/* r g b = 1 value, col = vector */
-static void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
+/* r g b = current value, col = new value, fac==0 is no change */
+/* if g==NULL, it only does r channel */
+void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
 {
        float tmp, facm= 1.0-fac;
        
        switch (type) {
        case MA_RAMP_BLEND:
                *r = facm*(*r) + fac*col[0];
-               *g = facm*(*g) + fac*col[1];
-               *b = facm*(*b) + fac*col[2];
+               if(g) {
+                       *g = facm*(*g) + fac*col[1];
+                       *b = facm*(*b) + fac*col[2];
+               }
                break;
        case MA_RAMP_ADD:
                *r += fac*col[0];
-               *g += fac*col[1];
-               *b += fac*col[2];
+               if(g) {
+                       *g += fac*col[1];
+                       *b += fac*col[2];
+               }
                break;
        case MA_RAMP_MULT:
                *r *= (facm + fac*col[0]);
-               *g *= (facm + fac*col[1]);
-               *b *= (facm + fac*col[2]);
+               if(g) {
+                       *g *= (facm + fac*col[1]);
+                       *b *= (facm + fac*col[2]);
+               }
                break;
        case MA_RAMP_SCREEN:
-               *r = 1.0-(facm + (1.0 - col[0]))*(1.0 - *r);
-               *g = 1.0-(facm + (1.0 - col[1]))*(1.0 - *g);
-               *b = 1.0-(facm + (1.0 - col[2]))*(1.0 - *b);
+               *r = 1.0 - (facm + fac*(1.0 - col[0])) * (1.0 - *r);
+               if(g) {
+                       *g = 1.0 - (facm + fac*(1.0 - col[1])) * (1.0 - *g);
+                       *b = 1.0 - (facm + fac*(1.0 - col[2])) * (1.0 - *b);
+               }
                break;
        case MA_RAMP_SUB:
                *r -= fac*col[0];
-               *g -= fac*col[1];
-               *b -= fac*col[2];
+               if(g) {
+                       *g -= fac*col[1];
+                       *b -= fac*col[2];
+               }
                break;
        case MA_RAMP_DIV:
                if(col[0]!=0.0)
                        *r = facm*(*r) + fac*(*r)/col[0];
-               if(col[1]!=0.0)
-                       *g = facm*(*g) + fac*(*g)/col[1];
-               if(col[2]!=0.0)
-                       *b = facm*(*b) + fac*(*b)/col[2];
+               if(g) {
+                       if(col[1]!=0.0)
+                               *g = facm*(*g) + fac*(*g)/col[1];
+                       if(col[2]!=0.0)
+                               *b = facm*(*b) + fac*(*b)/col[2];
+               }
                break;
        case MA_RAMP_DIFF:
                *r = facm*(*r) + fac*fabs(*r-col[0]);
-               *g = facm*(*g) + fac*fabs(*g-col[1]);
-               *b = facm*(*b) + fac*fabs(*b-col[2]);
+               if(g) {
+                       *g = facm*(*g) + fac*fabs(*g-col[1]);
+                       *b = facm*(*b) + fac*fabs(*b-col[2]);
+               }
                break;
        case MA_RAMP_DARK:
                tmp= fac*col[0];
                if(tmp < *r) *r= tmp; 
-               tmp= fac*col[1];
-               if(tmp < *g) *g= tmp; 
-               tmp= fac*col[2];
-               if(tmp < *b) *b= tmp; 
+               if(g) {
+                       tmp= fac*col[1];
+                       if(tmp < *g) *g= tmp; 
+                       tmp= fac*col[2];
+                       if(tmp < *b) *b= tmp; 
+                       }
                break;
        case MA_RAMP_LIGHT:
                tmp= fac*col[0];
                if(tmp > *r) *r= tmp; 
-               tmp= fac*col[1];
-               if(tmp > *g) *g= tmp; 
-               tmp= fac*col[2];
-               if(tmp > *b) *b= tmp; 
+               if(g) {
+                       tmp= fac*col[1];
+                       if(tmp > *g) *g= tmp; 
+                       tmp= fac*col[2];
+                       if(tmp > *b) *b= tmp; 
+               }
                break;
        }
 
@@ -1342,6 +1361,12 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
        
        memset(shr, 0, sizeof(ShadeResult));
        
+       /* copy all relevant material vars, note, keep this synced with render_types.h */
+       memcpy(&shi->r, &ma->r, 23*sizeof(float));
+       /* set special cases */
+       shi->har= ma->har;
+       if((ma->mode & MA_RAYMIRROR)==0) shi->ray_mirror= 0.0;
+       
        /* separate loop */
        if(ma->mode & MA_ONLYSHADOW) {
                float ir;
@@ -1760,21 +1785,14 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
 
        shr->alpha= shi->alpha;
 
-       if(shr->spec[0]<0.0) shr->spec[0]= 0.0;
-       if(shr->spec[1]<0.0) shr->spec[1]= 0.0;
-       if(shr->spec[2]<0.0) shr->spec[2]= 0.0;
-
        shr->diff[0]+= shi->r*shi->amb*shi->rad[0];
        shr->diff[0]+= shi->ambr;
-       if(shr->diff[0]<0.0) shr->diff[0]= 0.0;
        
        shr->diff[1]+= shi->g*shi->amb*shi->rad[1];
        shr->diff[1]+= shi->ambg;
-       if(shr->diff[1]<0.0) shr->diff[1]= 0.0;
        
        shr->diff[2]+= shi->b*shi->amb*shi->rad[2];
        shr->diff[2]+= shi->ambb;
-       if(shr->diff[2]<0.0) shr->diff[2]= 0.0;
        
        if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shr->diff, shi);
        if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shr->spec, shr->spec+1, shr->spec+2, shi);
@@ -1796,7 +1814,7 @@ void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, i
        VlakRen *vlr= shi->vlr;
        float l, dl;
        short texco= shi->mat->texco;
-       int mode= shi->mat->mode;
+       int mode= shi->mat->mode_l;             /* or-ed result for all layers */
        char p1, p2, p3;
        
        /* for rendering of quads, the following values are used to denote vertices:
@@ -2135,7 +2153,20 @@ static float isec_view_line(float *view, float *v3, float *v4)
 }
 #endif
 
-  
+void matlayer_blend(MaterialLayer *ml, float blendfac, ShadeResult *target, ShadeResult *src)
+{
+       
+       if(ml->flag & ML_DIFFUSE)
+               ramp_blend(ml->blendmethod, target->diff, target->diff+1, target->diff+2, blendfac*src->alpha, src->diff);
+       
+       if(ml->flag & ML_SPECULAR)
+               ramp_blend(ml->blendmethod, target->spec, target->spec+1, target->spec+2, blendfac*src->alpha, src->spec);
+       
+       if(ml->flag & ML_ALPHA)
+               ramp_blend(ml->blendmethod, &target->alpha, NULL, NULL, blendfac, &src->alpha);
+}
+
+
 /* x,y: window coordinate from 0 to rectx,y */
 /* return pointer to rendered face */
 void *shadepixel(float x, float y, int z, int facenr, int mask, float *col, float *rco)
@@ -2161,18 +2192,15 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col, floa
        }
        else if( (facenr & 0x7FFFFF) <= R.totvlak) {
                VertRen *v1, *v2, *v3;
+               Material *mat;
+               MaterialLayer *ml;
                float alpha, fac, zcor;
                
                vlr= RE_findOrAddVlak( (facenr-1) & 0x7FFFFF);
                
                shi.vlr= vlr;
-               shi.mat= vlr->mat;
+               mat= shi.mat= vlr->mat;
                
-               // copy all relevant material vars, note, keep this synced with render_types.h
-               memcpy(&shi.r, &shi.mat->r, 23*sizeof(float));
-               // set special cases:
-               shi.har= shi.mat->har;
-               if((shi.mat->mode & MA_RAYMIRROR)==0) shi.ray_mirror= 0.0;
                shi.osatex= (shi.mat->texco & TEXCO_OSA);
                
                /* copy the face normal (needed because it gets flipped for tracing */
@@ -2338,31 +2366,77 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col, floa
                        }
                }
                
-               /* ------  main shading loop */
-               shade_lamp_loop(&shi, &shr);
+               /* ------  main shading loop -------- */
+               VECCOPY(shi.vno, shi.vn);
+               
+               if(shi.mat->ml_flag & ML_RENDER) {
+
+                       shade_lamp_loop(&shi, &shr);    /* clears shr */
 
-               if(shi.translucency!=0.0) {
-                       ShadeResult shr_t;
+                       if(shi.translucency!=0.0) {
+                               ShadeResult shr_t;
+                               
+                               VECCOPY(shi.vn, shi.vno);
+                               VecMulf(shi.vn, -1.0);
+                               VecMulf(shi.facenor, -1.0);
+                               shade_lamp_loop(&shi, &shr_t);
+                               shr.diff[0]+= shi.translucency*shr_t.diff[0];
+                               shr.diff[1]+= shi.translucency*shr_t.diff[1];
+                               shr.diff[2]+= shi.translucency*shr_t.diff[2];
+                               VecMulf(shi.vn, -1.0);
+                               VecMulf(shi.facenor, -1.0);
+                       }
                        
-                       VecMulf(shi.vn, -1.0);
-                       VecMulf(shi.facenor, -1.0);
-                       shade_lamp_loop(&shi, &shr_t);
-                       shr.diff[0]+= shi.translucency*shr_t.diff[0];
-                       shr.diff[1]+= shi.translucency*shr_t.diff[1];
-                       shr.diff[2]+= shi.translucency*shr_t.diff[2];
-                       VecMulf(shi.vn, -1.0);
-                       VecMulf(shi.facenor, -1.0);
-               }
-               
-               if(R.r.mode & R_RAYTRACE) {
-                       if(shi.ray_mirror!=0.0 || ((shi.mat->mode & MA_RAYTRANSP) && shr.alpha!=1.0)) {
-                               ray_trace(&shi, &shr);
+                       if(R.r.mode & R_RAYTRACE) {
+                               if(shi.ray_mirror!=0.0 || ((shi.mat->mode & MA_RAYTRANSP) && shr.alpha!=1.0)) {
+                                       ray_trace(&shi, &shr);
+                               }
+                       }
+                       else {
+                               /* doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this */
+                               if(shi.mat->mode & MA_RAYTRANSP) shr.alpha= 1.0;
                        }
                }
                else {
-                       // doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this
-                       if(shi.mat->mode & MA_RAYTRANSP) shr.alpha= 1.0;
+                       memset(&shr, 0, sizeof(ShadeResult));
+                       shr.alpha= 1.0f;
+               }
+               
+               for(ml= shi.mat->layers.first; ml; ml= ml->next) {
+                       if(ml->mat && (ml->flag & ML_RENDER)) {
+                               ShadeResult shrlay;
+                               
+                               shi.mat= ml->mat;
+                               shi.layerfac= ml->blendfac;
+                               VECCOPY(shi.vn, shi.vno);
+                               if(ml->flag & ML_NEG_NORMAL)
+                                       VecMulf(shi.vn, -1.0);
+                               
+                               shade_lamp_loop(&shi, &shrlay); /* clears shrlay */
+                               
+                               if(R.r.mode & R_RAYTRACE) {
+                                       if(shi.ray_mirror!=0.0 || ((shi.mat->mode & MA_RAYTRANSP) && shr.alpha!=1.0)) {
+                                               ray_trace(&shi, &shr);
+                                       }
+                               }
+                               else {
+                                       /* doesnt look 'correct', but is better for preview, plus envmaps dont raytrace this */
+                                       if(shi.mat->mode & MA_RAYTRANSP) shr.alpha= 1.0;
+                               }
+                               
+                               matlayer_blend(ml, shi.layerfac, &shr, &shrlay);
+                       }
                }
+               shi.mat= mat;
+               
+               /* after shading and composit layers */
+               if(shr.spec[0]<0.0f) shr.spec[0]= 0.0f;
+               if(shr.spec[1]<0.0f) shr.spec[1]= 0.0f;
+               if(shr.spec[2]<0.0f) shr.spec[2]= 0.0f;
+               
+               if(shr.diff[0]<0.0f) shr.diff[0]= 0.0f;
+               if(shr.diff[1]<0.0f) shr.diff[1]= 0.0f;
+               if(shr.diff[2]<0.0f) shr.diff[2]= 0.0f;
                
                VECADD(col, shr.diff, shr.spec);
                
index 3653b82f581d78b7b84b4d6110070fae9cb4568d..344957608fe8795820e1a3a87a4d60743ff76715 100644 (file)
@@ -218,27 +218,6 @@ void init_render_textures()
 
 /* ------------------------------------------------------------------------- */
 
-void end_render_texture(Tex *tex)
-{
-
-
-}
-
-/* ------------------------------------------------------------------------- */
-
-void end_render_textures()
-{
-       Tex *tex;
-
-       tex= G.main->tex.first;
-       while(tex) {
-               if(tex->id.us) end_render_texture(tex);
-               tex= tex->id.next;
-       }
-
-}
-
-/* ------------------------------------------------------------------------- */
 
 /* this allows colorbanded textures to control normals as well */
 static void tex_normal_derivate(Tex *tex, TexResult *texres)
@@ -1292,9 +1271,9 @@ static void texture_rgb_blend(float *in, float *tex, float *out, float fact, flo
        case MTEX_SCREEN:
                fact*= facg;
                facm= 1.0-facg;
-               in[0]= 1.0-(facm+fact*(1.0-tex[0]))*(1.0-out[0]);
-               in[1]= 1.0-(facm+fact*(1.0-tex[1]))*(1.0-out[1]);
-               in[2]= 1.0-(facm+fact*(1.0-tex[2]))*(1.0-out[2]);
+               in[0]= 1.0 - (facm+fact*(1.0-tex[0])) * (1.0-out[0]);
+               in[1]= 1.0 - (facm+fact*(1.0-tex[1])) * (1.0-out[1]);
+               in[2]= 1.0 - (facm+fact*(1.0-tex[2])) * (1.0-out[2]);
                break;
 
        case MTEX_SUB:
@@ -1825,6 +1804,13 @@ void do_material_tex(ShadeInput *shi)
                                        if(shi->translucency<0.0) shi->translucency= 0.0;
                                        else if(shi->translucency>1.0) shi->translucency= 1.0;
                                }
+                               if(mtex->mapto & MAP_LAYER) {
+                                       int flip= mtex->maptoneg & MAP_LAYER;
+                                       
+                                       shi->layerfac= texture_value_blend(mtex->def_var, shi->layerfac, texres.tin, varfac, mtex->blendtype, flip);
+                                       if(shi->layerfac<0.0) shi->layerfac= 0.0;
+                                       else if(shi->layerfac>1.0) shi->layerfac= 1.0;
+                               }
                                if(mtex->mapto & MAP_AMB) {
                                        int flip= mtex->maptoneg & MAP_AMB;
 
index 07ae6dbcdd2f900b14ec4117ddc8c95782805888..665bd3ce6de1d02342e6ca6e1a203d7c54497ec7 100644 (file)
@@ -2424,8 +2424,6 @@ void RE_freeRotateBlenderScene(void)
 
        free_mesh_orco_hash();
 
-       end_render_textures();
-       end_render_materials();
        end_radio_render();
        if(R.wrld.aosphere) {
                MEM_freeN(R.wrld.aosphere);
index 73243750841e1610717522acdb1df8030dd045b4..c37544e911a88860e3e0cec3a32a6f4aa9878044 100644 (file)
@@ -376,17 +376,20 @@ static void drawcolorband_cb(void)
 {
        ID *id, *idfrom;
        
-       buttons_active_id(&id, &idfrom);
+       buttons_active_id(&id, &idfrom);        /* base material, not the matlayer! */
        if( GS(id->name)==ID_TE) {
                Tex *tex= (Tex *)id;
                drawcolorband(tex->coba, 10,145,300,30);
        }
        else if( GS(id->name)==ID_MA) {
                Material *ma= (Material *)id;
-               if(ma->ramp_show==0)
-                       drawcolorband(ma->ramp_col, 10,110,300,30);
-               else
-                       drawcolorband(ma->ramp_spec, 10,110,300,30);
+               ma= get_active_matlayer(ma);
+               if(ma) {
+                       if(ma->ramp_show==0)
+                               drawcolorband(ma->ramp_col, 10,110,300,30);
+                       else
+                               drawcolorband(ma->ramp_spec, 10,110,300,30);
+               }
        }
 }
 
@@ -756,7 +759,7 @@ void do_texbuts(unsigned short event)
                                do_colorbandbuts(tex->coba, event);
                        }
                        else {
-                               ma= (Material *)id;
+                               ma= get_active_matlayer((Material *)id);
                                if(ma->ramp_show==0) do_colorbandbuts(ma->ramp_col, event);
                                else do_colorbandbuts(ma->ramp_spec, event);
                        }
@@ -1422,7 +1425,10 @@ static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *l
        if(uiNewPanel(curarea, block, "Texture", "Texture", 320, 0, 318, 204)==0) return;
 
        /* first do the browse but */
-       buttons_active_id(&id, &idfrom);
+       id= (ID *)mtex->tex;
+       if(ma) idfrom= &ma->id;
+       else if(wrld) idfrom= &wrld->id;
+       else idfrom= &la->id;
 
        uiBlockSetCol(block, TH_BUT_SETTING2);
        if(ma) {
@@ -2012,16 +2018,12 @@ static void world_panel_amb_occ(World *wrld)
 static void world_panel_world(World *wrld)
 {
        uiBlock *block;
-       ID *id, *idfrom;
        
        block= uiNewBlock(&curarea->uiblocks, "world_panel_world", UI_EMBOSS, UI_HELV, curarea->win);
        if(uiNewPanel(curarea, block, "World", "World", 320, 0, 318, 204)==0) return;
 
-       /* first do the browse but */
-       buttons_active_id(&id, &idfrom);
-
        uiBlockSetCol(block, TH_BUT_SETTING2);
-       std_libbuttons(block, 10, 180, 0, NULL, B_WORLDBROWSE, id, idfrom, &(G.buts->menunr), B_WORLDALONE, B_WORLDLOCAL, B_WORLDDELETE, 0, B_KEEPDATA);
+       std_libbuttons(block, 10, 180, 0, NULL, B_WORLDBROWSE, (ID *)wrld, (ID *)G.scene, &(G.buts->menunr), B_WORLDALONE, B_WORLDLOCAL, B_WORLDDELETE, 0, B_KEEPDATA);
 
        if(wrld==NULL) return;
        
@@ -2455,7 +2457,6 @@ static void lamp_panel_yafray(Object *ob, Lamp *la)
 static void lamp_panel_lamp(Object *ob, Lamp *la)
 {
        uiBlock *block;
-       ID *id, *idfrom;
        float grid= 0.0;
        short xco;
        
@@ -2467,11 +2468,8 @@ static void lamp_panel_lamp(Object *ob, Lamp *la)
 
        uiSetButLock(la->id.lib!=0, "Can't edit library data");
 
-       /* first do the browse but */
-       buttons_active_id(&id, &idfrom);
-
        uiBlockSetCol(block, TH_BUT_SETTING2);
-       xco= std_libbuttons(block, 8, 180, 0, NULL, B_LAMPBROWSE, id, (ID *)ob, &(G.buts->menunr), B_LAMPALONE, B_LAMPLOCAL, 0, 0, 0);  
+       xco= std_libbuttons(block, 8, 180, 0, NULL, B_LAMPBROWSE, (ID *)la, (ID *)ob, &(G.buts->menunr), B_LAMPALONE, B_LAMPLOCAL, 0, 0, 0);    
 
        uiBlockSetCol(block, TH_AUTO);
        uiDefButF(block, NUM,B_LAMPREDRAW,"Dist:", xco,180,300-xco,20,&la->dist, 0.01, 5000.0*grid, 100, 0, "Sets the distance value at which light intensity is half");
@@ -2563,9 +2561,11 @@ void do_matbuts(unsigned short event)
        Material *ma;
        MTex *mtex;
 
+       /* all operations default on active material layer here */
+       ma = get_active_matlayer(G.buts->lockpoin);
+       
        switch(event) {
        case B_MAT_YF_PRESET: {
-               ma = G.buts->lockpoin;
                switch (ma->YF_preset) {
                        case 0:
                                /* normal mode, no reflection/refraction */
@@ -2645,7 +2645,6 @@ void do_matbuts(unsigned short event)
        case B_MATHALO:
                /* when halo is disabled, clear star flag, this is the same as MA_FACETEXTURE <blush> */
                /* same for 'xtreme alpha' which is 'only shadow' */
-               ma= G.buts->lockpoin;
                if((ma->mode & MA_HALO)==0) {
                        ma->mode &= ~(MA_STAR|MA_HALO_XALPHA|MA_ZINV);
                }
@@ -2654,7 +2653,6 @@ void do_matbuts(unsigned short event)
                shade_buttons_change_3d();
                break;
        case B_TEXCLEAR:
-               ma= G.buts->lockpoin;
                mtex= ma->mtex[(int) ma->texact ];
                if(mtex) {
                        if(mtex->tex) mtex->tex->id.us--;
@@ -2667,7 +2665,6 @@ void do_matbuts(unsigned short event)
                }
                break;
        case B_MTEXCOPY:
-               ma= G.buts->lockpoin;
                if(ma && ma->mtex[(int)ma->texact] ) {
                        mtex= ma->mtex[(int)ma->texact];
                        if(mtex->tex==0) {
@@ -2680,7 +2677,6 @@ void do_matbuts(unsigned short event)
                }
                break;
        case B_MTEXPASTE:
-               ma= G.buts->lockpoin;
                if(ma && mtexcopied && mtexcopybuf.tex) {
                        if(ma->mtex[(int)ma->texact]==0 ) 
                                ma->mtex[(int)ma->texact]= MEM_mallocN(sizeof(MTex), "mtex"); 
@@ -2696,14 +2692,12 @@ void do_matbuts(unsigned short event)
                }
                break;
        case B_MATLAY:
-               ma= G.buts->lockpoin;
                if(ma && ma->lay==0) {
                        ma->lay= 1;
                        scrarea_queue_winredraw(curarea);
                }
                break;
        case B_MATZTRANSP:
-               ma= G.buts->lockpoin;
                if(ma) {
                        ma->mode &= ~MA_RAYTRANSP;
                        allqueue(REDRAWBUTSSHADING, 0);
@@ -2711,7 +2705,6 @@ void do_matbuts(unsigned short event)
                }
                break;
        case B_MATRAYTRANSP:
-               ma= G.buts->lockpoin;
                if(ma) {
                        ma->mode &= ~MA_ZTRA;
                        allqueue(REDRAWBUTSSHADING, 0);
@@ -2719,7 +2712,6 @@ void do_matbuts(unsigned short event)
                }
                break;
        case B_MATCOLORBAND:
-               ma= G.buts->lockpoin;
                if(ma) {
                        if(ma->mode & MA_RAMP_COL)
                                if(ma->ramp_col==NULL) ma->ramp_col= add_colorband();
@@ -2731,7 +2723,33 @@ void do_matbuts(unsigned short event)
                        shade_buttons_change_3d();
                }
                break;
-
+       case B_MAT_LAYERBROWSE:
+               ma= G.buts->lockpoin;   /* use base material instead */
+               if(ma) {
+                       MaterialLayer *ml;
+                       
+                       /* the one with a menu set is the browser */
+                       for(ml= ma->layers.first; ml; ml= ml->next) {
+                               if(ml->menunr) {
+                                       if(ml->menunr==32767) {
+                                               if(ml->mat) {
+                                                       ml->mat->id.us--;
+                                                       ml->mat= copy_material(ml->mat);
+                                               }
+                                               else ml->mat= add_material("Layer");
+                                       }
+                                       else {
+                                               ml->mat= BLI_findlink(&G.main->mat, ml->menunr-1);
+                                               ml->mat->id.us++;
+                                       }
+                                       allqueue(REDRAWBUTSSHADING, 0);
+                                       BIF_all_preview_changed();
+                                       
+                                       break;
+                               }
+                       }
+               }
+               break;
        }
 }
 
@@ -2792,7 +2810,7 @@ static void material_panel_map_to(Material *ma)
        uiDefButBitS(block, TOG3, MAP_RAYMIRR, B_MATPRV, "RayMir",      60,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the ray-mirror value");
        uiDefButBitS(block, TOG3, MAP_ALPHA, B_MATPRV, "Alpha",         110,160,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the alpha value");
        uiDefButBitS(block, TOG3, MAP_EMIT, B_MATPRV, "Emit",           160,160,45,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the emit value");
-       uiDefButBitS(block, TOG3, MAP_TRANSLU, B_MATPRV, "Translu",     205,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the translucency value");
+       uiDefButBitS(block, TOG3, MAP_LAYER, B_MATPRV, "Layer",         205,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the layer blending value");
        uiDefButBitS(block, TOG3, MAP_DISPLACE, B_MATPRV, "Disp",               265,160,45,19, &(mtex->mapto), 0, 0, 0, 0, "Let the texture displace the surface");
        uiBlockEndAlign(block);
        
@@ -3155,9 +3173,188 @@ static void material_panel_shading(Material *ma)
                uiDefButBitI(block, TOG, MA_RADIO, 0,   "Radio",                        245,55,65,19, &(ma->mode), 0, 0, 0, 0, "Enables material for radiosity rendering");
 
        }
+}
+
+static void matlayer_add(void *ma_v, void *ml_v)
+{
+       Material *ma= ma_v;
+       MaterialLayer *ml= ml_v, *mlnew;
+       
+       mlnew= MEM_callocN(sizeof(MaterialLayer), "mat layer");
+       
+       if(ml==NULL) 
+               BLI_addhead(&ma->layers, mlnew);
+       else
+               BLI_insertlink(&ma->layers, ml, mlnew);
+       
+       mlnew->blendfac= 0.5f;
+       mlnew->flag= ML_RENDER|ML_DIFFUSE|ML_SPECULAR;
+       
+       BIF_undo_push("Add Material Layer");
+       allqueue(REDRAWBUTSSHADING, 0);
+}
+
+static void matlayer_moveUp(void *ma_v, void *ml_v)
+{
+       Material *ma= ma_v;
+       MaterialLayer *ml= ml_v;
+
+       if (ml->prev) {
+               BLI_remlink(&ma->layers, ml);
+               BLI_insertlink(&ma->layers, ml->prev->prev, ml);
+       }
+       
+       BIF_undo_push("Move Material Layer");
+}
 
+static void matlayer_moveDown(void *ma_v, void *ml_v)
+{
+       Material *ma= ma_v;
+       MaterialLayer *ml= ml_v;
+       
+       if (ml->next) {
+               BLI_remlink(&ma->layers, ml);
+               BLI_insertlink(&ma->layers, ml->next, ml);
+       }
+       
+       BIF_undo_push("Move Material Layer");
 }
 
+static void matlayer_del(void *ma_v, void *ml_v)
+{
+       Material *ma= ma_v;
+       MaterialLayer *ml= ml_v;
+       
+       BLI_remlink(&ma->layers, ml);
+       if(ml->mat) ml->mat->id.us--;
+       MEM_freeN(ml);
+
+       BIF_undo_push("Delete Material Layer");
+}
+
+static void matlayer_active(void *ma_v, void *ml_v)
+{
+       Material *ma= ma_v;
+       MaterialLayer *ml;
+       
+       for(ml= ma->layers.first; ml; ml= ml->next) {
+               if(ml==ml_v)
+                       ml->flag |= ML_ACTIVE;
+               else
+                       ml->flag &= ~ML_ACTIVE;
+       }
+       BIF_undo_push("Activate Material Layer");
+}
+
+static void material_panel_layers(Material *ma)
+{
+       uiBlock *block;
+       uiBut *but;
+       MaterialLayer *ml;
+       int yco= 155, rb_col;
+       char *strp;
+       
+       block= uiNewBlock(&curarea->uiblocks, "material_panel_layers", UI_EMBOSS, UI_HELV, curarea->win);
+       uiNewPanelTabbed("Preview", "Material");
+       if(uiNewPanel(curarea, block, "Layers", "Material", 0, 0, 318, 204)==0) return;
+       
+       uiNewPanelHeight(block, 204);
+       
+       /* Active button for current material */
+       uiBlockBeginAlign(block);
+       for(ml= ma->layers.first; ml; ml= ml->next)
+               if(ml->flag & ML_ACTIVE) break;
+       
+       if(ml==NULL)
+               but=uiDefIconBut(block, BUT, B_MATPRV_DRAW, ICON_MATERIAL,      10, 180, 20, 20, NULL, 0.0, 0.0, 0, 0, "Activate base Material");
+       else but=uiDefBut(block, BUT, B_MATPRV_DRAW, " ",               10, 180, 20, 20, NULL, 0.0, 0.0, 0, 0, "Activate base Material");
+       uiButSetFunc(but, matlayer_active, ma, NULL);
+       
+       /* Enable/disable for current material */
+       if(ma->ml_flag & ML_RENDER)
+               uiDefIconButBitS(block, TOG, ML_RENDER, B_MATPRV_DRAW, ICON_CHECKBOX_HLT,       30, 180, 20, 20, &ma->ml_flag, 0.0, 0.0, 0, 0, "Enable or disable base Material");
+       else uiDefButBitS(block, TOG, ML_RENDER, B_MATPRV, " ", 30, 180, 20, 20, &ma->ml_flag, 0.0, 0.0, 0, 0, "Enable or disable base Material");
+       
+       uiBlockEndAlign(block);
+       /* label */
+       uiDefBut(block, LABEL, B_NOP, ma->id.name+2,                    60, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
+       /* add layer */
+       but= uiDefBut(block, BUT, B_NOP, "Add Layer", 200, 180,110,20, NULL, 0, 0, 0, 0, "Add a new Material Layer");
+       uiButSetFunc(but, matlayer_add, ma, NULL);
+
+       
+       for(ml= ma->layers.first; ml; ml= ml->next) {
+               
+               /* rounded header */
+               rb_col= (ml->flag & ML_ACTIVE)?40:20;
+               uiDefBut(block, ROUNDBOX, B_DIFF, "", 8, yco-48, 304, 71, NULL, 5.0, 0.0, 3 , rb_col-20, ""); 
+               
+               /* Active button */
+               uiBlockBeginAlign(block);
+               if(ml->flag & ML_ACTIVE)
+                       but=uiDefIconBut(block, BUT, B_MATPRV_DRAW, ICON_MATERIAL,      10, yco, 20, 20, NULL, 0.0, 0.0, 0, 0, "Activate this layer");
+               else but=uiDefBut(block, BUT, B_MATPRV_DRAW, " ",               10, yco, 20, 20, NULL, 0.0, 0.0, 0, 0, "Activate this layer");
+               uiButSetFunc(but, matlayer_active, ma, ml);
+               
+               /* enable/disable button */
+               if(ml->flag & ML_RENDER)
+                       uiDefIconButBitS(block, TOG, ML_RENDER, B_MATPRV_DRAW, ICON_CHECKBOX_HLT,       30, yco, 20, 20, &ml->flag, 0.0, 0.0, 0, 0, "Enable or disable this layer");
+               else uiDefButBitS(block, TOG, ML_RENDER, B_MATPRV, " ", 30, yco, 20, 20, &ml->flag, 0.0, 0.0, 0, 0, "Enable or disable this layer");
+               
+               uiBlockBeginAlign(block);
+               
+               /* browse button */
+               IDnames_to_pupstring(&strp, NULL, "ADD NEW %x32767", &(G.main->mat), (ID *)ma, NULL);
+               ml->menunr= 0;
+               uiDefButS(block, MENU, B_MAT_LAYERBROWSE, strp, 60,yco,20,20, &ml->menunr, 0, 0, 0, 0, "Browses existing choices or adds NEW");
+               if(strp) MEM_freeN(strp);
+                       
+               /* name */
+               if(ml->mat) {
+                       but= uiDefBut(block, TEX, B_IDNAME, "MA:",80, yco, 120, 20, ml->mat->id.name+2, 0.0, 19.0, 0, 0, "Rename Material");
+                       uiButSetFunc(but, test_idbutton_cb, ml->mat->id.name, NULL);
+               }
+               else
+                       uiDefBut(block, LABEL, B_NOP, "No Material",80, yco, 120, 20, NULL, 0.0, 0.0, 0, 0, "");
+                       
+               /* add new */
+               but= uiDefBut(block, BUT, B_NOP, "Add", 200, yco,50,20, NULL, 0, 0, 0, 0, "Add a new Material Layer");
+               uiButSetFunc(but, matlayer_add, ma, ml);
+               
+               /* move up/down/delete */
+               but = uiDefIconBut(block, BUT, B_MATPRV_DRAW, VICON_MOVE_UP, 250, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Move layer up");
+               uiButSetFunc(but, matlayer_moveUp, ma, ml);
+               
+               but = uiDefIconBut(block, BUT, B_MATPRV_DRAW, VICON_MOVE_DOWN, 270, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Move layer down");
+               uiButSetFunc(but, matlayer_moveDown, ma, ml);
+               
+               but = uiDefIconBut(block, BUT, B_MATPRV_DRAW, VICON_X, 290, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete material layer");
+               uiButSetFunc(but, matlayer_del, ma, ml);
+               
+               /* blend slider and operation */
+               uiBlockBeginAlign(block);
+               yco-= 25;
+               uiDefButS(block, MENU, B_MATPRV, "Mix %x0|Add %x1|Subtract %x3|Multiply %x2|Screen %x4|Divide %x5|Difference %x6|Darken %x7|Lighten %x8",
+                                                                                                       35,yco,100,20, &ml->blendmethod, 0, 0, 0, 0, "Blending method for Ramp (uses alpha in Colorband)");
+               uiDefButF(block, NUMSLI, B_MATPRV, "Blend:",135,yco,175,20, &ml->blendfac, 0.0, 1.0, 100, 0, "Blending factor");
+               
+               /* output */
+               yco-=20;
+               uiDefButBitS(block, TOG, ML_DIFFUSE, B_MATPRV,  "Diff",         35,yco,50,20, &ml->flag, 0, 0, 0, 0, "This Layer affects Diffuse");
+               uiDefButBitS(block, TOG, ML_SPECULAR, B_MATPRV, "Spec", 85,yco,50,20, &ml->flag, 0, 0, 0, 0, "This Layer affects Specular");
+               uiDefButBitS(block, TOG, ML_ALPHA, B_MATPRV, "Alpha",           135,yco,50,20, &ml->flag, 0, 0, 0, 0, "This Layer affects Alpha");
+               uiDefButBitS(block, TOG, ML_NEG_NORMAL, B_MATPRV, "Negate Normal",      185,yco,125,20, &ml->flag, 0, 0, 0, 0, "Negate normal for this layer");
+               
+               yco-= 30;
+               
+               uiBlockEndAlign(block);
+       }
+       
+       if(yco < 0) uiNewPanelHeight(block, 204-yco);
+
+}
+
+
 static void material_panel_ramps(Material *ma)
 {
        uiBlock *block;
@@ -3240,7 +3437,7 @@ static void material_panel_material(Object *ob, Material *ma)
        if(uiNewPanel(curarea, block, "Material", "Material", 320, 0, 318, 204)==0) return;
 
        /* first do the browse but */
-       buttons_active_id(&id, &idfrom);
+       buttons_active_id(&id, &idfrom);        /* base material, not the matlayer! */
 
        uiBlockSetCol(block, TH_BUT_SETTING2);
        std_libbuttons(block, 8, 200, 0, NULL, B_MATBROWSE, id, idfrom, &(G.buts->menunr), B_MATALONE, B_MATLOCAL, B_MATDELETE, B_AUTOMATNAME, B_KEEPDATA);
@@ -3281,8 +3478,8 @@ static void material_panel_material(Object *ob, Material *ma)
        if(ob->totcol==0) return;
        uiSetButLock(id->lib!=0, "Can't edit library data");
 
-       ma= give_current_material(ob, ob->actcol);      
-       if(ma==0) return;       
+       ma= get_active_matlayer(ma);
+       if(ma==NULL) return;    
        
        if(ma->dynamode & MA_DRAW_DYNABUTS) {
                uiBlockBeginAlign(block);
@@ -3401,23 +3598,30 @@ void material_panels()
                material_panel_material(ob, ma);
                
                if(ma) {
-                       material_panel_ramps(ma);
-                       material_panel_shading(ma);
-                       if (G.scene->r.renderer==R_INTERN)
-                               material_panel_tramir(ma);
-                       else {
-                               if (ma->YF_ar==0.f) {
-                                       ma->YF_ar = ma->YF_ag = ma->YF_ab = 1;
-                                       ma->YF_dscale = 1;
-                               }
-                               material_panel_tramir_yafray(ma);
-                       }
-                       material_panel_texture(ma);
+                       material_panel_layers(ma);
                        
-                       mtex= ma->mtex[ ma->texact ];
-                       if(mtex && mtex->tex) {
-                               material_panel_map_input(ob, ma);
-                               material_panel_map_to(ma);
+                       ma= get_active_matlayer(ma);
+                       if(ma) {
+                               material_panel_ramps(ma);
+                               material_panel_shading(ma);
+                               
+                               if (G.scene->r.renderer==R_INTERN)
+                                       material_panel_tramir(ma);
+                               else {
+                                       if(ma->YF_ar==0.f) {
+                                               ma->YF_ar = ma->YF_ag = ma->YF_ab = 1;
+                                               ma->YF_dscale = 1;
+                                       }
+                                       material_panel_tramir_yafray(ma);
+                               }
+                               
+                               material_panel_texture(ma);
+                               
+                               mtex= ma->mtex[ ma->texact ];
+                               if(mtex && mtex->tex) {
+                                       material_panel_map_input(ob, ma);
+                                       material_panel_map_to(ma);
+                               }
                        }
                }
        }
@@ -3478,6 +3682,7 @@ void texture_panels()
        if(G.buts->texfrom==0) {
                if(ob) {
                        ma= give_current_material(ob, ob->actcol);
+                       ma= get_active_matlayer(ma);
                        if(ma) mtex= ma->mtex[ ma->texact ];
                }
        }
@@ -3601,8 +3806,8 @@ void clever_numbuts_buts()
                break;
        case TAB_SHADING_MAT:
 
-               ma= G.buts->lockpoin;
-
+               ma= get_active_matlayer(G.buts->lockpoin);
+               
                /* Build a hex value */
                if (ma){
                        sprintf(hexrgb, "%02X%02X%02X", (int)(ma->r*255), (int)(ma->g*255), (int)(ma->b*255));
index b470d2ab6afa1eb93d2742288bc1b42bdc2bc8c0..d4654dd671807332da863d1fd56c4d49e84e2a45 100644 (file)
@@ -343,7 +343,6 @@ static void draw_bgpic(void)
                init_render_texture(bgpic->tex);
                free_unused_animimages();
                ima= bgpic->tex->ima;
-               end_render_texture(bgpic->tex);
        }
        else {
                ima= bgpic->ima;
index 811dbd79f23c26e9e9ee0921210a7752add4790d..bb5f66e4932f9fcb1174325109357f702748844e 100644 (file)
@@ -3994,6 +3994,40 @@ void single_user(void)
 
 /* ************************************************************* */
 
+/* helper for below, ma was checked to be not NULL */
+static void make_local_makelocalmaterial(Material *ma)
+{
+       MaterialLayer *ml;
+       ID *id;
+       int b;
+       
+       make_local_material(ma);
+       
+       for(b=0; b<MAX_MTEX; b++) {
+               if(ma->mtex[b] && ma->mtex[b]->tex) {
+                       make_local_texture(ma->mtex[b]->tex);
+               }
+       }
+       
+       id= (ID *)ma->ipo;
+       if(id && id->lib) make_local_ipo(ma->ipo);      
+       
+       for(ml=ma->layers.first; ml; ml= ml->next) {
+               if(ml->mat) {
+                       make_local_material(ml->mat);
+                       
+                       for(b=0; b<MAX_MTEX; b++) {
+                               if(ml->mat->mtex[b] && ml->mat->mtex[b]->tex) {
+                                       make_local_texture(ml->mat->mtex[b]->tex);
+                               }
+                       }
+                       
+                       id= (ID *)ml->mat->ipo;
+                       if(id && id->lib) make_local_ipo(ml->mat->ipo); 
+               }
+               
+       }
+}
 
 void make_local(void)
 {
@@ -4116,34 +4150,16 @@ void make_local(void)
                                
                                for(a=0; a<ob->totcol; a++) {
                                        ma= ob->mat[a];
-                                       if(ma) {
-                                               make_local_material(ma);
-                                       
-                                               for(b=0; b<MAX_MTEX; b++) {
-                                                       if(ma->mtex[b] && ma->mtex[b]->tex) {
-                                                               make_local_texture(ma->mtex[b]->tex);
-                                                       }
-                                               }
-                                               id= (ID *)ma->ipo;
-                                               if(id && id->lib) make_local_ipo(ma->ipo);      
-                                       }
+                                       if(ma)
+                                               make_local_makelocalmaterial(ma);
                                }
                                
                                matarar= (Material ***)give_matarar(ob);
                                
                                for(a=0; a<ob->totcol; a++) {
                                        ma= (*matarar)[a];
-                                       if(ma) {
-                                               make_local_material(ma);
-                                       
-                                               for(b=0; b<MAX_MTEX; b++) {
-                                                       if(ma->mtex[b] && ma->mtex[b]->tex) {
-                                                               make_local_texture(ma->mtex[b]->tex);
-                                                       }
-                                               }
-                                               id= (ID *)ma->ipo;
-                                               if(id && id->lib) make_local_ipo(ma->ipo);      
-                                       }
+                                       if(ma)
+                                               make_local_makelocalmaterial(ma);
                                }
                        }
                }
index 7b992263bb7f5d45b5b653a48205c32ce04bd280..9d8f05aa835a6d1a6ea90bb38f26d2434bdaefa0 100644 (file)
@@ -62,6 +62,7 @@
 #include "BIF_butspace.h"
 
 #include "BKE_armature.h"
+#include "BKE_blender.h"
 #include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
@@ -72,6 +73,7 @@
 #include "BSE_headerbuttons.h"
 
 #include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
 
 #include "blendef.h"
 #include "mydevice.h"
@@ -98,9 +100,12 @@ void free_matcopybuf(void)
  
        if(matcopybuf.ramp_col) MEM_freeN(matcopybuf.ramp_col);
        if(matcopybuf.ramp_spec) MEM_freeN(matcopybuf.ramp_spec);
+       
        matcopybuf.ramp_col= NULL;
        matcopybuf.ramp_spec= NULL;
        
+       BLI_freelistN(&matcopybuf.layers);
+       
        default_mtex(&mtexcopybuf);
 }
 
@@ -109,6 +114,7 @@ void do_buts_buttons(short event)
        static short matcopied=0;
        MTex *mtex;
        Material *ma;
+       MaterialLayer *ml;
        ID id;
        int a;
        float dx, dy;
@@ -143,9 +149,10 @@ void do_buts_buttons(short event)
                break;
        case B_MATCOPY:
                if(G.buts->lockpoin) {
+                       ma= G.buts->lockpoin;
                        if(matcopied) free_matcopybuf();
 
-                       memcpy(&matcopybuf, G.buts->lockpoin, sizeof(Material));
+                       memcpy(&matcopybuf, ma, sizeof(Material));
                        if(matcopybuf.ramp_col) matcopybuf.ramp_col= MEM_dupallocN(matcopybuf.ramp_col);
                        if(matcopybuf.ramp_spec) matcopybuf.ramp_spec= MEM_dupallocN(matcopybuf.ramp_spec);
 
@@ -155,12 +162,15 @@ void do_buts_buttons(short event)
                                        matcopybuf.mtex[a]= MEM_dupallocN(mtex);
                                }
                        }
+                       duplicatelist(&matcopybuf.layers, &ma->layers);
+                       
                        matcopied= 1;
                }
                break;
        case B_MATPASTE:
                if(matcopied && G.buts->lockpoin) {
                        ma= G.buts->lockpoin;
+                       
                        /* free current mat */
                        if(ma->ramp_col) MEM_freeN(ma->ramp_col);
                        if(ma->ramp_spec) MEM_freeN(ma->ramp_spec);
@@ -169,6 +179,10 @@ void do_buts_buttons(short event)
                                if(mtex && mtex->tex) mtex->tex->id.us--;
                                if(mtex) MEM_freeN(mtex);
                        }
+                       for(ml= ma->layers.first; ml; ml= ml->next)
+                               if(ml->mat) ml->mat->id.us--;
+
+                       BLI_freelistN(&ma->layers);
                        
                        id= (ma->id);
                        memcpy(G.buts->lockpoin, &matcopybuf, sizeof(Material));
@@ -184,6 +198,11 @@ void do_buts_buttons(short event)
                                        if(mtex->tex) id_us_plus((ID *)mtex->tex);
                                }
                        }
+                       duplicatelist(&ma->layers, &matcopybuf.layers);
+
+                       for(ml= ma->layers.first; ml; ml= ml->next)
+                               if(ml->mat) ml->mat->id.us++;
+                       
                        BIF_preview_changed(G.buts);
                        BIF_undo_push("Paste material settings");
                        scrarea_queue_winredraw(curarea);
index c9383d2dded6e69c56eceb09d569c7e76fb4ab5f..d05904c74a82a2eefe47e25019f23e2cfa1cd3af 100644 (file)
@@ -809,6 +809,7 @@ void do_global_buttons(unsigned short event)
                else {
                        if(G.buts->texfrom==0) {        /* from mat */
                                ma= give_current_material(ob, ob->actcol);
+                               ma= get_active_matlayer(ma);
                                if(ma) {
                                        mtex= ma->mtex[ ma->texact ];
                                        if(mtex) {
@@ -861,6 +862,7 @@ void do_global_buttons(unsigned short event)
                        if(event==B_EXTEXBROWSE) {
                                id= NULL;
                                ma= give_current_material(ob, ob->actcol);
+                               ma= get_active_matlayer(ma);
                                if(ma) {
                                        mtex= ma->mtex[ ma->texact ];
                                        if(mtex) id= (ID *)mtex->tex;
@@ -879,6 +881,7 @@ void do_global_buttons(unsigned short event)
                        id= NULL;
                        
                        ma= give_current_material(ob, ob->actcol);
+                       ma= get_active_matlayer(ma);
                        if(ma) {
                                mtex= ma->mtex[ ma->texact ];
                                if(mtex) id= (ID *)mtex->tex;
@@ -1717,7 +1720,13 @@ void do_global_buttons2(short event)
                        ma= give_current_material(ob, ob->actcol);
                        if(ma && ma->id.lib) {
                                if(okee("Make local")) {
+                                       MaterialLayer *ml;
+                                       
                                        make_local_material(ma);
+                                       for(ml= ma->layers.first; ml; ml= ml->next) {
+                                               if(ml->mat)
+                                                       make_local_material(ml->mat);
+                                       }
                                }
                        }
                }
@@ -1790,6 +1799,7 @@ void do_global_buttons2(short event)
                if(G.buts->texfrom==0) {        /* from mat */
                        if(ob==0) return;
                        ma= give_current_material(ob, ob->actcol);
+                       ma= get_active_matlayer(ma);
                        if(ma && ma->id.lib==0) {
                                mtex= ma->mtex[ ma->texact ];
                                if(mtex->tex && mtex->tex->id.us>1) {
@@ -1830,6 +1840,7 @@ void do_global_buttons2(short event)
                if(G.buts->texfrom==0) {        /* from mat */
                        if(ob==0) return;
                        ma= give_current_material(ob, ob->actcol);
+                       ma= get_active_matlayer(ma);
                        if(ma && ma->id.lib==0) {
                                mtex= ma->mtex[ ma->texact ];
                                if(mtex->tex && mtex->tex->id.lib) {
index 54bab5703a34c78ca01d78c571f41c0cfb71ef38..c9892ed7f1edbcbc71946a104aad485b398514ba 100644 (file)
@@ -652,7 +652,7 @@ void uiSetPanel_view2d(ScrArea *sa)
        
        pa= sa->panels.first;
        while(pa) {
-               if(pa->active) {
+               if(pa->active && pa->paneltab==NULL) {
                        done= 1;
                        if(pa->ofsx < minx) minx= pa->ofsx;
                        if(pa->ofsx+pa->sizex > maxx) maxx= pa->ofsx+pa->sizex;
@@ -696,7 +696,7 @@ void uiMatchPanel_view2d(ScrArea *sa)
        
        pa= sa->panels.first;
        while(pa) {
-               if(pa->active) {
+               if(pa->active && pa->paneltab==NULL) {
                        done= 1;
                        if(pa->ofsx < G.v2d->tot.xmin) G.v2d->tot.xmin= pa->ofsx;
                        if(pa->ofsx+pa->sizex > G.v2d->tot.xmax) 
index 5761d0af36cec268f60b444580d1992fe76485d3..759baa72e5c91e1f05f325a60980bff0598aed52 100644 (file)
@@ -1,7 +1,4 @@
-/* previewrender.c             GRAPHICS
- * 
- * maart 95
- * 
+/* 
  * $Id$
  *
  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
@@ -130,26 +127,26 @@ static short snijpunt(float *v1,   float *v2,  float *v3,  float *rtlabda, float
        x2= t10*t21-t11*t20;
 
        deeldet= t00*x0+t01*x1+t02*x2;
-       if(deeldet!=0.0) {
+       if(deeldet!=0.0f) {
                m0= ray1[0]-v3[0];
                m1= ray1[1]-v3[1];
                m2= ray1[2]-v3[2];
                det1= m0*x0+m1*x1+m2*x2;
                rtu= det1/deeldet;
-               if(rtu<=0.0) {
+               if(rtu<=0.0f) {
                        det2= t00*(m1*t22-m2*t21);
                        det2+= t01*(m2*t20-m0*t22);
                        det2+= t02*(m0*t21-m1*t20);
                        rtv= det2/deeldet;
-                       if(rtv<=0.0) {
-                               if(rtu+rtv>= -1.0) {
+                       if(rtv<=0.0f) {
+                               if(rtu+rtv>= -1.0f) {
                                        
                                        det3=  m0*(t12*t01-t11*t02);
                                        det3+= m1*(t10*t02-t12*t00);
                                        det3+= m2*(t11*t00-t10*t01);
                                        *rtlabda= det3/deeldet;
                                        
-                                       if(*rtlabda>=0.0 && *rtlabda<=1.0) {
+                                       if(*rtlabda>=0.0f && *rtlabda<=1.0f) {
                                                return 1;
                                        }
                                }
@@ -176,7 +173,7 @@ static int rcubi[3][4]= {
 
 static int ray_previewrender(int x,  int y,  float *vec, float *vn)
 {
-       float scalef= 10.0/100.0;
+       float scalef= 10.0f/100.0f;
        float ray1[3], ray2[3];
        float minlabda, labda;
        int totface= 3, hitface= -1;
@@ -184,10 +181,10 @@ static int ray_previewrender(int x,  int y,  float *vec, float *vn)
 
        ray1[0]= ray2[0]= x*scalef;
        ray1[1]= ray2[1]= y*scalef;
-       ray1[2]= -10.0;
-       ray2[2]= 10.0;
+       ray1[2]= -10.0f;
+       ray2[2]= 10.0f;
        
-       minlabda= 1.0;
+       minlabda= 1.0f;
        for(a=0; a<totface; a++) {
                if(snijpunt( rcubev[rcubi[a][0]], rcubev[rcubi[a][1]], rcubev[rcubi[a][2]], &labda, ray1, ray2)) {
                        if( labda < minlabda) {
@@ -252,8 +249,8 @@ static void set_previewrect(int win, int xmin, int ymin, int xmax, int ymax)
        pr_sizex= (prerect.xmax-prerect.xmin);
        pr_sizey= (prerect.ymax-prerect.ymin);
 
-       pr_facx= ( pr_sizex-1.0)/PR_RECTX;
-       pr_facy= ( pr_sizey-1.0)/PR_RECTY;
+       pr_facx= ( pr_sizex-1.0f)/PR_RECTX;
+       pr_facy= ( pr_sizey-1.0f)/PR_RECTY;
 
        /* correction for gla draw */
        prerect.xmin-= curarea->winrct.xmin;
@@ -277,7 +274,7 @@ static void end_previewrect(void)
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
        
-       glPixelZoom(1.0, 1.0);
+       glPixelZoom(1.0f, 1.0f);
        
        // restore viewport / scissor which was set by glaDefine2DArea
        glViewport(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx, curarea->winy);
@@ -309,10 +306,10 @@ static void draw_tex_crop(Tex *tex)
        if(tex==0) return;
        
        if(tex->type==TEX_IMAGE) {
-               if(tex->cropxmin==0.0) ret++;
-               if(tex->cropymin==0.0) ret++;
-               if(tex->cropxmax==1.0) ret++;
-               if(tex->cropymax==1.0) ret++;
+               if(tex->cropxmin==0.0f) ret++;
+               if(tex->cropymin==0.0f) ret++;
+               if(tex->cropxmax==1.0f) ret++;
+               if(tex->cropymax==1.0f) ret++;
                if(ret==4) return;
                
                rct.xmin= PR_XMIN+2+tex->cropxmin*(PR_XMAX-PR_XMIN-4);
@@ -405,7 +402,7 @@ static void sky_preview_pixel(float lens, int x, int y, char *rect)
        if(R.wrld.skytype & WO_SKYPAPER) {
                view[0]= (2*x)/(float)PR_RECTX;
                view[1]= (2*y)/(float)PR_RECTY;
-               view[2]= 0.0;
+               view[2]= 0.0f;
        }
        else {
                view[0]= x;
@@ -425,9 +422,9 @@ static void lamp_preview_pixel(ShadeInput *shi, LampRen *la, int x, int y, char
        shi->co[1]= (float)y/(PR_RECTX/4);
        shi->co[2]= 0;
        
-       vec[0]= 0.02*x;
-       vec[1]= 0.02*y;
-       vec[2]= 0.005*PR_RECTX;
+       vec[0]= 0.02f*x;
+       vec[1]= 0.02f*y;
+       vec[2]= 0.005f*PR_RECTX;
        VECCOPY(shi->view, vec);
        dist= Normalise(shi->view);
 
@@ -438,16 +435,16 @@ static void lamp_preview_pixel(ShadeInput *shi, LampRen *la, int x, int y, char
        if(la->mode & LA_TEXTURE) do_lamp_tex(la, vec, shi, lacol);
 
        if(la->type==LA_SUN || la->type==LA_HEMI) {
-               dist= 1.0;
+               dist= 1.0f;
        }
        else {
                
                if(la->mode & LA_QUAD) {
                        
-                       t= 1.0;
-                       if(la->ld1>0.0)
+                       t= 1.0f;
+                       if(la->ld1>0.0f)
                                t= la->dist/(la->dist+la->ld1*dist);
-                       if(la->ld2>0.0) {
+                       if(la->ld2>0.0f) {
                                distkw= la->dist*la->dist;
                                t= t*distkw/(t*distkw+la->ld2*dist*dist);
                        }
@@ -471,10 +468,10 @@ static void lamp_preview_pixel(ShadeInput *shi, LampRen *la, int x, int y, char
                }
                
                t= la->spotsi;
-               if(inpr<t) dist= 0.0;
+               if(inpr<t) dist= 0.0f;
                else {
                        t= inpr-t;
-                       if(t<la->spotbl && la->spotbl!=0.0) {
+                       if(t<la->spotbl && la->spotbl!=0.0f) {
                                /* soft area */
                                i= t/la->spotbl;
                                t= i*i;
@@ -577,9 +574,9 @@ static void previewflare(SpaceButs *sbuts, HaloRen *har, unsigned int *rect)
        afmy= R.afmy;
        rectot= R.rectot;
 
-       R.r.postmul= R.r.postgamma= R.r.postsat= 1.0;
-       R.r.posthue= R.r.postadd= 0.0;
-       R.ycor= 1.0;
+       R.r.postmul= R.r.postgamma= R.r.postsat= 1.0f;
+       R.r.posthue= R.r.postadd= 0.0f;
+       R.ycor= 1.0f;
        R.rectx= PR_RECTX;      
        R.recty= PR_RECTY;
        R.afmx= PR_RECTX/2;
@@ -609,11 +606,11 @@ static void previewflare(SpaceButs *sbuts, HaloRen *har, unsigned int *rect)
 static void texture_preview_pixel(Tex *tex, int x, int y, char *rect)
 {
        float i, v1, xsq, ysq, texvec[3];
-       float tin=1.0, tr, tg, tb, ta;
+       float tin=1.0f, tr, tg, tb, ta;
        int rgbnor, tracol, skip=0;
        
        if(tex->type==TEX_IMAGE) {
-               v1= 1.0/PR_RECTX;
+               v1= 1.0f/PR_RECTX;
                
                texvec[0]= 0.5+v1*x;
                texvec[1]= 0.5+v1*y;
@@ -622,11 +619,11 @@ static void texture_preview_pixel(Tex *tex, int x, int y, char *rect)
                if(tex->extend==TEX_REPEAT) {
                        if(tex->xrepeat>1) {
                                texvec[0] *= tex->xrepeat;
-                               if(texvec[0]>1.0) texvec[0] -= (int)(texvec[0]);
+                               if(texvec[0]>1.0f) texvec[0] -= (int)(texvec[0]);
                        }
                        if(tex->yrepeat>1) {
                                texvec[1] *= tex->yrepeat;
-                               if(texvec[1]>1.0) texvec[1] -= (int)(texvec[1]);
+                               if(texvec[1]>1.0f) texvec[1] -= (int)(texvec[1]);
                        }
                }
                else if(tex->extend==TEX_CHECKER) {
@@ -647,17 +644,17 @@ static void texture_preview_pixel(Tex *tex, int x, int y, char *rect)
                                i= 2.0*(texvec[2]);
                                texvec[0]= (i*texvec[0]);
                                texvec[1]= (i*texvec[1]);
-                               texvec[2]= (-1.0+i*texvec[2]);
+                               texvec[2]= (-1.0f+i*texvec[2]);
 
                        }
                        else {
                                skip= 1;
-                               tr= tg= tb= ta= 0.0;
+                               tr= tg= tb= ta= 0.0f;
                        }
                }
                else {
                        skip= 1;
-                       tr= tg= tb= ta= 0.0;
+                       tr= tg= tb= ta= 0.0f;
                }
        }
        else {
@@ -665,7 +662,7 @@ static void texture_preview_pixel(Tex *tex, int x, int y, char *rect)
        
                texvec[0]= v1*x;
                texvec[1]= v1*y;
-               texvec[2]= 0.0;
+               texvec[2]= 0.0f;
        }
        
        if(skip==0) rgbnor= multitex_ext(tex, texvec, &tin, &tr, &tg, &tb, &ta);
@@ -680,9 +677,9 @@ static void texture_preview_pixel(Tex *tex, int x, int y, char *rect)
                v1= 255.0*tb;
                rect[2]= CLAMPIS(v1, 0, 255);
                
-               if(ta!=1.0) {
+               if(ta!=1.0f) {
                        tracol=  64+100*(abs(x)>abs(y));
-                       tracol= (1.0-ta)*tracol;
+                       tracol= (1.0f-ta)*tracol;
                        
                        rect[0]= tracol+ (rect[0]*ta) ;
                        rect[1]= tracol+ (rect[1]*ta) ;
@@ -706,24 +703,24 @@ static void refraction_prv(int *x, int *y, float *n, float index)
 {
        float dot, fac, view[3], len;
 
-       index= 1.0/index;
+       index= 1.0f/index;
        
        view[0]= index*(float)*x;
        view[1]= ((float)*y)/index;
-       view[2]= 20.0;
+       view[2]= 20.0f;
        len= Normalise(view);
        
        dot= view[0]*n[0] + view[1]*n[1] + view[2]*n[2];
 
-       if(dot>0.0) {
-               fac= 1.0 - (1.0 - dot*dot)*index*index;
-               if(fac<= 0.0) return;
+       if(dot>0.0f) {
+               fac= 1.0f - (1.0f - dot*dot)*index*index;
+               if(fac<= 0.0f) return;
                fac= -dot*index + sqrt(fac);
        }
        else {
-               index = 1.0/index;
-               fac= 1.0 - (1.0 - dot*dot)*index*index;
-               if(fac<= 0.0) return;
+               index = 1.0f/index;
+               fac= 1.0f - (1.0f - dot*dot)*index*index;
+               if(fac<= 0.0f) return;
                fac= -dot*index - sqrt(fac);
        }
 
@@ -731,157 +728,62 @@ static void refraction_prv(int *x, int *y, float *n, float index)
        *y= (int)(len*(index*view[1] + fac*n[1]));
 }
 
-
-static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y,char *rect, int smooth)
+static void shade_lamp_loop_preview(ShadeInput *shi, ShadeResult *shr, int pr_lamp)
 {
        extern float fresnel_fac(float *view, float *vn, float ior, float fac);
-       Material *mat;
-       float v1,inp, is, inprspec=0, isr=0.0, isb=0.0, isg=0.0;
-       float diff[3]={0.0, 0.0, 0.0};
-       float lv[3], *la, alpha;
-       float eul[3], tmat[3][3], imat[3][3];
-       int temp, a;
-       char tracol;
-               
-       mat= shi->mat;
-
+       Material *mat= shi->mat;
+       float inp, is, inprspec=0;
+       float lv[3], *la;
+       int a;
+       
        // copy all relevant material vars, note, keep this synced with render_types.h
        memcpy(&shi->r, &mat->r, 23*sizeof(float));
        // set special cases:
        shi->har= mat->har;
-       if((mat->mode & MA_RAYMIRROR)==0) shi->ray_mirror= 0.0;
        
-       v1= 1.0/PR_RECTX;
-       shi->view[0]= v1*x;
-       shi->view[1]= v1*y;
-       shi->view[2]= 1.0;
-       Normalise(shi->view);
+       if((mat->mode & MA_RAYMIRROR)==0) shi->ray_mirror= 0.0f;
+       memset(shr, 0, sizeof(ShadeResult));
        
-       shi->xs= (float)x;
-       shi->ys= (float)y;
+       /* normals flipped in render for smooth... */
+       if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0f);
        
-       shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0;
-
-       /* texture handling */
-       if(mat->texco) {
-               
-               VECCOPY(shi->lo, vec);
-               
-               if(mat->pr_type==MA_CUBE) {
-                       
-                       eul[0]= (297)*M_PI/180.0;
-                       eul[1]= 0.0;
-                       eul[2]= (45)*M_PI/180.0;
-                       EulToMat3(eul, tmat);
-
-                       MTC_Mat3MulVecfl(tmat, shi->lo);
-                       MTC_Mat3MulVecfl(tmat, shi->vn);
-                       /* hack for cubemap, why!!! */
-                       SWAP(float, shi->vn[0], shi->vn[1]);
-               }
-               /* textures otherwise upside down */
-               if(mat->pr_type==MA_CUBE || mat->pr_type==MA_SPHERE) 
-                       shi->lo[2]= -shi->lo[2];
-
-               if(mat->texco & TEXCO_GLOB) {
-                       VECCOPY(shi->gl, shi->lo);
-               }
-               if(mat->texco & TEXCO_WINDOW) {
-                       VECCOPY(shi->winco, shi->lo);
-               }
-               if(mat->texco & TEXCO_STICKY) {
-                       VECCOPY(shi->sticky, shi->lo);
-               }
-               if(mat->texco & TEXCO_UV) {
-                       VECCOPY(shi->uv, shi->lo);
-               }
-               if(mat->texco & TEXCO_STRAND) {
-                       shi->strand= shi->lo[0];
-               }
-               if(mat->texco & TEXCO_OBJECT) {
-                       VECCOPY(shi->co, shi->lo);
-               }
-               if(mat->texco & (TEXCO_NORM)) {
-                       shi->orn[0]= shi->vn[0];
-                       shi->orn[1]= shi->vn[1];
-                       shi->orn[2]= shi->vn[2];
-               }
-               if(mat->texco & TEXCO_REFL) {
-                       
-                       inp= -2.0*(shi->vn[0]*shi->view[0]+shi->vn[1]*shi->view[1]+shi->vn[2]*shi->view[2]);
-                       shi->ref[0]= (shi->view[0]+inp*shi->vn[0]);
-                       shi->ref[1]= (shi->view[1]+inp*shi->vn[1]);
-                       shi->ref[2]= (shi->view[2]+inp*shi->vn[2]);
-               }
-
-               /* Clear displase vec for preview */
-               shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0;
-               
-               /* normals flipped in render for smooth... */
-               if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0);
-               
-               do_material_tex(shi);
-
-               /* normals flipped in render... */
-               if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0);
+       do_material_tex(shi);
+       
+       /* normals flipped in render... */
+       if( (mat->mapto & MAP_NORM)) VecMulf(shi->vn, -1.0f);   
+       
+       shr->alpha= shi->alpha;
        
-               if(mat->texco & TEXCO_REFL) {
-                       /* normals in render are pointing different... rhm */
-                       if(smooth) shi->ref[1]= -shi->ref[1];
-               }
-
-               if(mat->pr_type==MA_CUBE) {
-                       /* rotate normal back for normals texture */
-                       SWAP(float, shi->vn[0], shi->vn[1]);
-                       MTC_Mat3Inv(imat, tmat);
-                       MTC_Mat3MulVecfl(imat, shi->vn);
-               }
-               
-       }
-       /* set it here, because ray_mirror will affect it */
-       alpha= shi->alpha;
-
-       if(mat->mapto & MAP_DISPLACE) { /* Quick hack of fake displacement preview */
-               shi->vn[0]-=2.0*shi->displace[2];
-               shi->vn[1]-=2.0*shi->displace[0];
-               shi->vn[2]+=2.0*shi->displace[1];
-               Normalise(shi->vn);
-       }
-               
        if(mat->mode & (MA_ZTRA|MA_RAYTRANSP)) 
-               if(mat->fresnel_tra!=0.0) 
-                       alpha*= fresnel_fac(shi->view, shi->vn, mat->fresnel_tra_i, mat->fresnel_tra);
-
+               if(mat->fresnel_tra!=0.0f
+                       shr->alpha*= fresnel_fac(shi->view, shi->vn, mat->fresnel_tra_i, mat->fresnel_tra);
+       
        if(mat->mode & MA_SHLESS) {
-               temp= 255.0*(shi->r);
-               if(temp>255) rect[0]= 255; else if(temp<0) rect[0]= 0; else rect[0]= temp;
-
-               temp= 255.0*(shi->g);
-               if(temp>255) rect[1]= 255; else if(temp<0) rect[1]= 0; else rect[1]= temp;
-
-               temp= 255.0*(shi->b);
-               if(temp>255) rect[2]= 255; else if(temp<0) rect[2]= 0; else rect[2]= temp;
+               shr->diff[0]= shi->r;
+               shr->diff[1]= shi->g;
+               shr->diff[2]= shi->b;
+               
        }
        else {
                
                for(a=0; a<2; a++) {
                        
-                       if((mat->pr_lamp & (1<<a))==0) continue;
+                       if((pr_lamp & (1<<a))==0) continue;
                        
                        if(a==0) la= pr1_lamp;
                        else la= pr2_lamp;
                        
-                       lv[0]= vec[0]-la[0];
-                       lv[1]= vec[1]-la[1];
-                       lv[2]= vec[2]-la[2];
+                       lv[0]= shi->co[0]-la[0];
+                       lv[1]= shi->co[1]-la[1];
+                       lv[2]= shi->co[2]-la[2];
                        Normalise(lv);
                        
                        is= shi->vn[0]*lv[0]+shi->vn[1]*lv[1]+shi->vn[2]*lv[2];
-                       if(is<0.0) is= 0.0;
+                       if(is<0.0f) is= 0.0f;
                        
-                       if(shi->spec>0.0)  {
+                       if(shi->spec>0.0f)  {
                                
-                               if(is>0.0) {
+                               if(is>0.0f) {
                                        /* specular shaders */
                                        float specfac;
                                        
@@ -895,20 +797,20 @@ static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y,char *
                                                specfac= WardIso_Spec(shi->vn, lv, shi->view, mat->rms, 0);
                                        else 
                                                specfac= Toon_Spec(shi->vn, lv, shi->view, mat->param[2], mat->param[3], 0);
-                               
+                                       
                                        inprspec= specfac*shi->spec;
                                        
                                        if(mat->mode & MA_RAMP_SPEC) {
                                                float spec[3];
                                                do_specular_ramp(shi, specfac, inprspec, spec);
-                                               isr+= inprspec*spec[0];
-                                               isg+= inprspec*spec[1];
-                                               isb+= inprspec*spec[2];
+                                               shr->spec[0]+= inprspec*spec[0];
+                                               shr->spec[1]+= inprspec*spec[1];
+                                               shr->spec[2]+= inprspec*spec[2];
                                        }
                                        else {  
-                                               isr+= inprspec*shi->specr;
-                                               isg+= inprspec*shi->specg;
-                                               isb+= inprspec*shi->specb;
+                                               shr->spec[0]+= inprspec*shi->specr;
+                                               shr->spec[1]+= inprspec*shi->specg;
+                                               shr->spec[2]+= inprspec*shi->specb;
                                        }
                                }
                        }
@@ -922,12 +824,10 @@ static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y,char *
                        
                        if(a==0) la= pr1_col;
                        else la= pr2_col;
-
-                       add_to_diffuse(diff, shi, is, inp*la[0], inp*la[1], inp*la[2]);
-                       //ir+= inp*la[0];
-                       //ig+= inp*la[1];
-                       //ib+= inp*la[2];
+                       
+                       add_to_diffuse(shr->diff, shi, is, inp*la[0], inp*la[1], inp*la[2]);
                }
+               /* end lamp loop */
                
                /* drawing checkerboard and sky */
                if(mat->mode & MA_RAYMIRROR) {
@@ -940,93 +840,240 @@ static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y,char *
                        shi->ref[2]= 0.17*y + 0.98*z;
                        
                        /* scale */
-                       div= (0.85*shi->ref[1]);
+                       div= (0.85f*shi->ref[1]);
                        
                        shi->refcol[0]= shi->ray_mirror*fresnel_fac(shi->view, shi->vn, mat->fresnel_mir_i, mat->fresnel_mir);
                        /* not real 'alpha', but mirror overriding transparency */
                        if(mat->mode & MA_RAYTRANSP) {
                                float fac= sqrt(shi->refcol[0]);
-                               alpha= alpha*(1.0-fac) + fac;
+                               shr->alpha= shr->alpha*(1.0f-fac) + fac;
                        }
-                       else alpha= alpha*(1.0-shi->refcol[0]) + shi->refcol[0];
+                       else shr->alpha= shr->alpha*(1.0f-shi->refcol[0]) + shi->refcol[0];
                        
-                       if(div<0.0) {
+                       if(div<0.0f) {
                                /* minus 0.5 prevents too many small tiles in distance */
-                               fac= (int)(shi->ref[0]/(div-0.1) ) + (int)(shi->ref[2]/(div-0.1) );
-                               if(fac & 1) col= 0.8;
-                               else col= 0.3;
-
+                               fac= (int)(shi->ref[0]/(div-0.1f) ) + (int)(shi->ref[2]/(div-0.1f) );
+                               if(fac & 1) col= 0.8f;
+                               else col= 0.3f;
+                               
                                shi->refcol[1]= shi->refcol[0]*col;
                                shi->refcol[2]= shi->refcol[1];
                                shi->refcol[3]= shi->refcol[2];
                        }
                        else {
-                               shi->refcol[1]= 0.0;
-                               shi->refcol[2]= shi->refcol[0]*0.3*div;
-                               shi->refcol[3]= shi->refcol[0]*0.8*div;
+                               shi->refcol[1]= 0.0f;
+                               shi->refcol[2]= shi->refcol[0]*0.3f*div;
+                               shi->refcol[3]= shi->refcol[0]*0.8f*div;
                        }
                }
                
-               if(mat->mode & MA_RAMP_COL) ramp_diffuse_result(diff, shi);
-               if(mat->mode & MA_RAMP_SPEC) ramp_spec_result(&isr, &isg, &isb, shi);
+               shr->diff[0]+= shi->ambr;
+               shr->diff[1]+= shi->ambg;
+               shr->diff[2]+= shi->ambb;
+               
+               if(mat->mode & MA_RAMP_COL) ramp_diffuse_result(shr->diff, shi);
+               if(mat->mode & MA_RAMP_SPEC) ramp_spec_result(shr->spec, shr->spec+1, shr->spec+2, shi);
                
-               if(shi->refcol[0]==0.0) {
-                       a= 255.0*(diff[0] +shi->ambr +isr);
-                       if(a>255) a=255; else if(a<0) a= 0;
-                       rect[0]= a;
-                       a= 255.0*(diff[1] +shi->ambg +isg);
-                       if(a>255) a=255; else if(a<0) a= 0;
-                       rect[1]= a;
-                       a= 255*(diff[2] +shi->ambb +isb);
-                       if(a>255) a=255; else if(a<0) a= 0;
-                       rect[2]= a;
+               /* refcol */
+               if(shi->refcol[0]!=0.0f) {
+                       shr->diff[0]= shi->mirr*shi->refcol[1] + (1.0f - shi->mirr*shi->refcol[0])*shr->diff[0];
+                       shr->diff[1]= shi->mirg*shi->refcol[2] + (1.0f - shi->mirg*shi->refcol[0])*shr->diff[1];
+                       shr->diff[2]= shi->mirb*shi->refcol[3] + (1.0f - shi->mirb*shi->refcol[0])*shr->diff[2];
                }
-               else {
-                       a= 255.0*( shi->mirr*shi->refcol[1] + (1.0 - shi->mirr*shi->refcol[0])*(diff[0] +shi->ambr) +isr);
-                       if(a>255) a=255; else if(a<0) a= 0;
-                       rect[0]= a;
-                       a= 255.0*( shi->mirg*shi->refcol[2] + (1.0 - shi->mirg*shi->refcol[0])*(diff[1] +shi->ambg) +isg);
-                       if(a>255) a=255; else if(a<0) a= 0;
-                       rect[1]= a;
-                       a= 255.0*( shi->mirb*shi->refcol[3] + (1.0 - shi->mirb*shi->refcol[0])*(diff[2] +shi->ambb) +isb);
-                       if(a>255) a=255; else if(a<0) a= 0;
-                       rect[2]= a;
+       
+               /* ztra shade */
+               if(shi->spectra!=0.0f) {
+                       inp = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]);
+                       inp *= shi->spectra;
+                       if(inp>1.0f) inp= 1.0f;
+                       shr->alpha= (1.0f-inp)*shr->alpha+inp;
                }
+       }       
+}
+
+static void shade_preview_pixel(ShadeInput *shi, float *vec, int x, int y, char *rect, int smooth)
+{
+       Material *mat;
+       MaterialLayer *ml;
+       ShadeResult shr;
+       float v1, inp;
+       float eul[3], tmat[3][3], imat[3][3], col[3];
+       char tracol;
+               
+       mat= shi->mat;
+
+       v1= 1.0/PR_RECTX;
+       shi->view[0]= v1*x;
+       shi->view[1]= v1*y;
+       shi->view[2]= 1.0f;
+       Normalise(shi->view);
+       
+       shi->xs= (float)x;
+       shi->ys= (float)y;
+       
+       shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0f;
+       VECCOPY(shi->co, vec);
+       
+       /* texture handling */
+       if(mat->texco) {
+               
+               VECCOPY(shi->lo, vec);
+               
+               if(mat->pr_type==MA_CUBE) {
+                       
+                       eul[0]= (297)*M_PI/180.0;
+                       eul[1]= 0.0;
+                       eul[2]= (45)*M_PI/180.0;
+                       EulToMat3(eul, tmat);
+
+                       MTC_Mat3MulVecfl(tmat, shi->lo);
+                       MTC_Mat3MulVecfl(tmat, shi->vn);
+                       /* hack for cubemap, why!!! */
+                       SWAP(float, shi->vn[0], shi->vn[1]);
+               }
+               /* textures otherwise upside down */
+               if(mat->pr_type==MA_CUBE || mat->pr_type==MA_SPHERE) 
+                       shi->lo[2]= -shi->lo[2];
+
+               if(mat->texco & TEXCO_GLOB) {
+                       VECCOPY(shi->gl, shi->lo);
+               }
+               if(mat->texco & TEXCO_WINDOW) {
+                       VECCOPY(shi->winco, shi->lo);
+               }
+               if(mat->texco & TEXCO_STICKY) {
+                       VECCOPY(shi->sticky, shi->lo);
+               }
+               if(mat->texco & TEXCO_UV) {
+                       VECCOPY(shi->uv, shi->lo);
+               }
+               if(mat->texco & TEXCO_STRAND) {
+                       shi->strand= shi->lo[0];
+               }
+               if(mat->texco & TEXCO_OBJECT) {
+                       /* nothing */
+               }
+               if(mat->texco & (TEXCO_NORM)) {
+                       shi->orn[0]= shi->vn[0];
+                       shi->orn[1]= shi->vn[1];
+                       shi->orn[2]= shi->vn[2];
+               }
+               if(mat->texco & TEXCO_REFL) {
+                       
+                       inp= -2.0*(shi->vn[0]*shi->view[0]+shi->vn[1]*shi->view[1]+shi->vn[2]*shi->view[2]);
+                       shi->ref[0]= (shi->view[0]+inp*shi->vn[0]);
+                       shi->ref[1]= (shi->view[1]+inp*shi->vn[1]);
+                       shi->ref[2]= (shi->view[2]+inp*shi->vn[2]);
+               }
+
+               /* Clear displase vec for preview */
+               shi->displace[0]= shi->displace[1]= shi->displace[2]= 0.0;
+                       
+               if(mat->texco & TEXCO_REFL) {
+                       /* normals in render are pointing different... rhm */
+                       if(smooth) shi->ref[1]= -shi->ref[1];
+               }
+
+               if(mat->pr_type==MA_CUBE) {
+                       /* rotate normal back for normals texture */
+                       SWAP(float, shi->vn[0], shi->vn[1]);
+                       MTC_Mat3Inv(imat, tmat);
+                       MTC_Mat3MulVecfl(imat, shi->vn);
+               }
+               
        }
 
-               /* ztra shade */
-       if(shi->spectra!=0.0) {
-               inp = MAX3(isr, isg, isb);
-               inp *= shi->spectra;
-               if(inp>1.0) inp= 1.0;
-               alpha= (1.0-inp)*alpha+inp;
+       if(mat->mapto & MAP_DISPLACE) { /* Quick hack of fake displacement preview */
+//             shi->vn[0]-=2.0*shi->displace[2];
+//             shi->vn[1]-=2.0*shi->displace[0];
+//             shi->vn[2]+=2.0*shi->displace[1];
+//             Normalise(shi->vn);
+       }
+
+       /* ------  main shading loop with material layers */
+       VECCOPY(shi->vno, shi->vn);
+       if(mat->ml_flag & ML_RENDER) 
+               shade_lamp_loop_preview(shi, &shr, mat->pr_lamp);
+       else {
+               memset(&shr, 0, sizeof(ShadeResult));
+               shr.alpha= 1.0f;
        }
 
-       if(alpha!=1.0) {
+       for(ml= mat->layers.first; ml; ml= ml->next) {
+               if(ml->mat && (ml->flag & ML_RENDER)) {
+                       ShadeResult shrlay;
+                       
+                       shi->mat= ml->mat;
+                       shi->layerfac= ml->blendfac;
+                       VECCOPY(shi->vn, shi->vno);
+                       if(ml->flag & ML_NEG_NORMAL)
+                               VecMulf(shi->vn, -1.0);
+
+                       shade_lamp_loop_preview(shi, &shrlay, mat->pr_lamp);
+                       matlayer_blend(ml, shi->layerfac, &shr, &shrlay);
+               }
+       }
+
+       shi->mat= mat;  /* restore, shade input is re-used! */
+
+       /* after shading and composit layers */
+       if(shr.spec[0]<0.0f) shr.spec[0]= 0.0f;
+       if(shr.spec[1]<0.0f) shr.spec[1]= 0.0f;
+       if(shr.spec[2]<0.0f) shr.spec[2]= 0.0f;
+
+       if(shr.diff[0]<0.0f) shr.diff[0]= 0.0f;
+       if(shr.diff[1]<0.0f) shr.diff[1]= 0.0f;
+       if(shr.diff[2]<0.0f) shr.diff[2]= 0.0f;
+
+       VECADD(col, shr.diff, shr.spec);
+       if(col[0]<=0.0f) rect[0]= 0; else if(col[0]>=1.0f) rect[0]= 255; else rect[0]= (char)(255.0*col[0]);
+       if(col[1]<=0.0f) rect[1]= 0; else if(col[1]>=1.0f) rect[1]= 255; else rect[1]= (char)(255.0*col[1]);
+       if(col[2]<=0.0f) rect[2]= 0; else if(col[2]>=1.0f) rect[2]= 255; else rect[2]= (char)(255.0*col[2]);
+
+       if(shr.alpha!=1.0f) {
                if(mat->mode & MA_RAYTRANSP) {
                        refraction_prv(&x, &y, shi->vn, shi->ang);
                }
                
                tracol=  previewback(mat->pr_back, x, y) & 255;
                
-               tracol= (1.0-alpha)*tracol;
+               tracol= (1.0f-shr.alpha)*tracol;
                
                if((mat->mode & MA_RAYTRANSP) && mat->filter!=0.0) {
-                       float fr= 1.0+ mat->filter*(shi->r-1.0);
-                       rect[0]= fr*tracol+ (rect[0]*alpha) ;
-                       fr= 1.0+ mat->filter*(shi->g-1.0);
-                       rect[1]= fr*tracol+ (rect[1]*alpha) ;
-                       fr= 1.0+ mat->filter*(shi->b-1.0);
-                       rect[2]= fr*tracol+ (rect[2]*alpha) ;
+                       float fr= 1.0f+ mat->filter*(shr.diff[0]-1.0f);
+                       rect[0]= fr*tracol+ (rect[0]*shr.alpha) ;
+                       fr= 1.0f+ mat->filter*(shr.diff[0]-1.0f);
+                       rect[1]= fr*tracol+ (rect[1]*shr.alpha) ;
+                       fr= 1.0f+ mat->filter*(shr.diff[0]-1.0f);
+                       rect[2]= fr*tracol+ (rect[2]*shr.alpha) ;
                }
                else {
-                       rect[0]= tracol+ (rect[0]*alpha) ;
-                       rect[1]= tracol+ (rect[1]*alpha) ;
-                       rect[2]= tracol+ (rect[2]*alpha) ;
+                       rect[0]= tracol+ (rect[0]*shr.alpha) ;
+                       rect[1]= tracol+ (rect[1]*shr.alpha) ;
+                       rect[2]= tracol+ (rect[2]*shr.alpha) ;
                }
        }
 }
 
+static void preview_init_render_textures(MTex **mtex)
+{
+       int x;
+       
+       for(x=0; x<MAX_MTEX; x++) {
+               if(mtex[x]) {
+                       if(mtex[x]->tex) {
+                               init_render_texture(mtex[x]->tex);
+                               
+                               if(mtex[x]->tex->env && mtex[x]->tex->env->object) 
+                                       MTC_Mat4One(mtex[x]->tex->env->object->imat);
+                               
+                       }
+                       if(mtex[x]->object) MTC_Mat4One(mtex[x]->object->imat);
+                       if(mtex[x]->object) MTC_Mat4One(mtex[x]->object->imat);
+               }
+       }
+       
+}
 
 void BIF_previewrender(SpaceButs *sbuts)
 {
@@ -1100,27 +1147,23 @@ void BIF_previewrender(SpaceButs *sbuts)
        shi.osatex= 0;
        
        if(mat) {
+               MaterialLayer *ml;
+               
                /* rendervars */
                init_render_world();
                init_render_material(mat);
+               /* also clears imats */
+               preview_init_render_textures(mat->mtex);
                
-               /* clear imats, flip normal... (hack because everything is inverted here) */
-               for(x=0; x<MAX_MTEX; x++) {
-                       if(mat->mtex[x]) {
-                               if(mat->mtex[x]->tex) {
-                                       init_render_texture(mat->mtex[x]->tex);
-                                       
-                                       if(mat->mtex[x]->tex->env && mat->mtex[x]->tex->env->object) 
-                                               MTC_Mat4One(mat->mtex[x]->tex->env->object->imat);
-                                       
-                                       mat->mtex[x]->maptoneg ^= MAP_NORM;
-                               }
-                               if(mat->mtex[x]->object) MTC_Mat4One(mat->mtex[x]->object->imat);
-                               if(mat->mtex[x]->object) MTC_Mat4One(mat->mtex[x]->object->imat);
+               for(ml= mat->layers.first; ml; ml= ml->next) {
+                       if(ml->mat && (ml->flag & ML_RENDER)) {
+                               init_render_material(ml->mat);
+                               preview_init_render_textures(ml->mat->mtex);
+                               mat->texco |= ml->mat->texco;
                        }
                }
-               shi.vlr= 0;
                
+               shi.vlr= NULL;          
                shi.mat= mat;
                
                if(mat->mode & MA_HALO) init_previewhalo(&har, mat);
@@ -1141,15 +1184,15 @@ void BIF_previewrender(SpaceButs *sbuts)
        else if(la) {
 
                init_render_world();
-               init_render_textures(); /* do not do it twice!! (brightness) */
+               preview_init_render_textures(la->mtex);
                R.totlamp= 0;
                RE_add_render_lamp(ob, 0);      /* 0=no shadbuf or tables */
                lar= R.la[0];
                
                /* exceptions: */
-               lar->spottexfac= 1.0;
-               lar->spotsi= cos( M_PI/3.0 );
-               lar->spotbl= (1.0-lar->spotsi)*la->spotblend;
+               lar->spottexfac= 1.0f;
+               lar->spotsi= cos( M_PI/3.0f );
+               lar->spotbl= (1.0f-lar->spotsi)*la->spotblend;
                
                MTC_Mat3One(lar->imat);
        }
@@ -1165,7 +1208,7 @@ void BIF_previewrender(SpaceButs *sbuts)
                        MTC_Mat4Invert(R.viewmat, R.viewinv);
                }
                init_render_world();
-               init_render_textures(); /* dont do it twice!! (brightness) */
+               preview_init_render_textures(wrld->mtex);       
        }
 
        uiPanelPush(block);     // sets UImat
@@ -1258,12 +1301,12 @@ void BIF_previewrender(SpaceButs *sbuts)
                                                }
                                        }
                                        else {
-                                               vec[0]= x*(2.0/PR_RECTX);
-                                               vec[1]= y*(2.0/PR_RECTX);
+                                               vec[0]= x*(2.0f/PR_RECTX);
+                                               vec[1]= y*(2.0f/PR_RECTX);
                                                vec[2]= 0.0;
                                                
-                                               shi.vn[0]= shi.vn[1]= 0.0;
-                                               shi.vn[2]= 1.0;
+                                               shi.vn[0]= shi.vn[1]= 0.0f;
+                                               shi.vn[2]= 1.0f;
                                                
                                                shade_preview_pixel(&shi, vec, x, y, (char *)rect, 0);
                                        }
@@ -1317,27 +1360,11 @@ void BIF_previewrender(SpaceButs *sbuts)
 
        uiPanelPop(block);
        
-       if(mat) {
-               end_render_material(mat);
-               for(x=0; x<MAX_MTEX; x++) {
-                       if(mat->mtex[x] && mat->mtex[x]->tex) {
-                               end_render_texture(mat->mtex[x]->tex);
-                               mat->mtex[x]->maptoneg ^= MAP_NORM;
-                       }       
-               }
-       }
-       else if(tex) {
-               end_render_texture(tex);
-       }
-       else if(la) {
+       if(la) {
                if(R.totlamp) {
                        MEM_freeN(R.la[0]);
                }
                R.totlamp= 0;
-               end_render_textures();
-       }
-       else if(wrld) {
-               end_render_textures();
        }
 }