Comments
[blender.git] / source / blender / render / intern / source / shadeoutput.c
index 7505b0fa5679cfa9f5b2ac0e28507a7b44789a72..427d0eeed11fa4de58f249e6051935dae4d12c99 100644 (file)
@@ -71,7 +71,7 @@ extern struct Render R;
 ListBase *get_lights(ShadeInput *shi)
 {
        
-       if (R.r.scemode & R_PREVIEWBUTS)
+       if (R.r.scemode & R_BUTS_PREVIEW)
                return &R.lights;
        if (shi->light_override)
                return &shi->light_override->gobject;
@@ -181,7 +181,8 @@ static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
        double a, b, c, disc, nray[3], npos[3];
        double t0, t1 = 0.0f, t2= 0.0f, t3;
        float p1[3], p2[3], ladist, maxz = 0.0f, maxy = 0.0f, haint;
-       int snijp, do_clip = TRUE, use_yco = FALSE;
+       int cuts;
+       bool do_clip = true, use_yco = false;
 
        *intens= 0.0f;
        haint= lar->haint;
@@ -217,7 +218,7 @@ static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
 
        /* rotate maxz */
        if (shi->co[2]==0.0f) {
-               do_clip = FALSE;  /* for when halo at sky */
+               do_clip = false;  /* for when halo at sky */
        }
        else {
                p1[0]= shi->co[0]-lar->co[0];
@@ -228,8 +229,8 @@ static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
                maxz*= lar->sh_zfac;
                maxy= lar->imat[0][1]*p1[0]+lar->imat[1][1]*p1[1]+lar->imat[2][1]*p1[2];
 
-               if (fabsf(nray[2]) < FLT_EPSILON) {
-                       use_yco = TRUE;
+               if (fabs(nray[2]) < FLT_EPSILON) {
+                       use_yco = true;
                }
        }
        
@@ -244,7 +245,7 @@ static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
        b = nray[0] * npos[0] + nray[1] * npos[1] - nray[2]*npos[2];
        c = npos[0] * npos[0] + npos[1] * npos[1] - npos[2]*npos[2];
 
-       snijp= 0;
+       cuts= 0;
        if (fabs(a) < DBL_EPSILON) {
                /*
                 * Only one intersection point...
@@ -256,16 +257,16 @@ static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
                
                if (disc==0.0) {
                        t1=t2= (-b)/ a;
-                       snijp= 2;
+                       cuts= 2;
                }
                else if (disc > 0.0) {
                        disc = sqrt(disc);
                        t1 = (-b + disc) / a;
                        t2 = (-b - disc) / a;
-                       snijp= 2;
+                       cuts= 2;
                }
        }
-       if (snijp==2) {
+       if (cuts==2) {
                int ok1=0, ok2=0;
 
                /* sort */
@@ -285,7 +286,7 @@ static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
                if (ok1==0 && ok2==0) return;
                
                /* intersction point with -ladist, the bottom of the cone */
-               if (use_yco == FALSE) {
+               if (use_yco == false) {
                        t3= ((double)(-ladist)-npos[2])/nray[2];
                                
                        /* de we have to replace one of the intersection points? */
@@ -319,7 +320,7 @@ static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens)
                
                /* calculate t0: is the maximum visible z (when halo is intersected by face) */ 
                if (do_clip) {
-                       if (use_yco == FALSE) t0 = ((double)maxz - npos[2]) / nray[2];
+                       if (use_yco == false) t0 = ((double)maxz - npos[2]) / nray[2];
                        else                  t0 = ((double)maxy - npos[1]) / nray[1];
 
                        if (t0 < t1) return;
@@ -924,6 +925,21 @@ void shade_color(ShadeInput *shi, ShadeResult *shr)
        shr->diff[1]= shi->g;
        shr->diff[2]= shi->b;
        shr->alpha= shi->alpha;
+
+       /* modulate by the object color */
+       if ((ma->shade_flag & MA_OBCOLOR) && shi->obr->ob) {
+               float obcol[4];
+
+               copy_v4_v4(obcol, shi->obr->ob->col);
+               CLAMP(obcol[3], 0.0f, 1.0f);
+
+               shr->diff[0] *= obcol[0];
+               shr->diff[1] *= obcol[1];
+               shr->diff[2] *= obcol[2];
+               if (shi->mode & MA_TRANSP) shr->alpha *= obcol[3];
+       }
+
+       copy_v3_v3(shr->diffshad, shr->diff);
 }
 
 /* ramp for at end of shade */
@@ -1178,8 +1194,8 @@ float lamp_get_visibility(LampRen *lar, const float co[3], float lv[3], float *d
                float visifac= 1.0f, t;
                
                sub_v3_v3v3(lv, co, lar->co);
-               *dist= sqrtf(dot_v3v3(lv, lv));
-               t= 1.0f/dist[0];
+               *dist = len_v3(lv);
+               t = 1.0f / (*dist);
                mul_v3_fl(lv, t);
                
                /* area type has no quad or sphere option */
@@ -1450,9 +1466,11 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int
                                                shr->shad[1] -= shadfac[3]*shi->g*(1.0f-lashdw[1]);
                                                shr->shad[2] -= shadfac[3]*shi->b*(1.0f-lashdw[2]);
                                                
-                                               shr->spec[0] -= shadfac[3]*shi->specr*(1.0f-lashdw[0]);
-                                               shr->spec[1] -= shadfac[3]*shi->specg*(1.0f-lashdw[1]);
-                                               shr->spec[2] -= shadfac[3]*shi->specb*(1.0f-lashdw[2]);
+                                               if (!(lar->mode & LA_NO_SPEC)) {
+                                                       shr->spec[0] -= shadfac[3]*shi->specr*(1.0f-lashdw[0]);
+                                                       shr->spec[1] -= shadfac[3]*shi->specg*(1.0f-lashdw[1]);
+                                                       shr->spec[2] -= shadfac[3]*shi->specb*(1.0f-lashdw[2]);
+                                               }
                                                
                                                return;
                                        }
@@ -1688,9 +1706,19 @@ static void wrld_exposure_correct(float diff[3])
 
 void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
 {
+       /* Passes which might need to know material color.
+        *
+        * It seems to be faster to just calculate material color
+        * even if the pass doesn't really need it than trying to
+        * figure out whether color is really needed or not.
+        */
+       const int color_passes =
+               SCE_PASS_COMBINED | SCE_PASS_RGBA | SCE_PASS_DIFFUSE | SCE_PASS_SPEC |
+               SCE_PASS_REFLECT | SCE_PASS_NORMAL | SCE_PASS_REFRACT | SCE_PASS_EMIT;
+
        Material *ma= shi->mat;
        int passflag= shi->passflag;
-       
+
        memset(shr, 0, sizeof(ShadeResult));
        
        if (!(shi->mode & MA_TRANSP)) shi->alpha = 1.0f;
@@ -1705,7 +1733,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
        shi->refcol[0]= shi->refcol[1]= shi->refcol[2]= shi->refcol[3]= 0.0f;
        
        /* material color itself */
-       if (passflag & (SCE_PASS_COMBINED|SCE_PASS_RGBA)) {
+       if (passflag & color_passes) {
                if (ma->mode & (MA_FACETEXTURE)) {
                        shi->r= shi->vcol[0];
                        shi->g= shi->vcol[1];
@@ -1776,18 +1804,20 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
        }
        
        /* AO pass */
-       if (R.wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) {
-               if (((passflag & SCE_PASS_COMBINED) && (shi->combinedflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) ||
-                   (passflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT)))
-               {
-                       if (R.r.mode & R_SHADOW) {
-                               /* AO was calculated for scanline already */
-                               if (shi->depth || shi->volume_depth)
-                                       ambient_occlusion(shi);
-                               copy_v3_v3(shr->ao, shi->ao);
-                               copy_v3_v3(shr->env, shi->env); /* XXX multiply */
-                               copy_v3_v3(shr->indirect, shi->indirect); /* XXX multiply */
-                       }
+       if (((passflag & SCE_PASS_COMBINED) && (shi->combinedflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) ||
+           (passflag & (SCE_PASS_AO|SCE_PASS_ENVIRONMENT|SCE_PASS_INDIRECT))) {
+               if ((R.wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && (R.r.mode & R_SHADOW)) {
+                       /* AO was calculated for scanline already */
+                       if (shi->depth || shi->volume_depth)
+                               ambient_occlusion(shi);
+                       copy_v3_v3(shr->ao, shi->ao);
+                       copy_v3_v3(shr->env, shi->env); /* XXX multiply */
+                       copy_v3_v3(shr->indirect, shi->indirect); /* XXX multiply */
+               }
+               else {
+                       shr->ao[0]= shr->ao[1]= shr->ao[2]= 1.0f;
+                       zero_v3(shr->env);
+                       zero_v3(shr->indirect);
                }
        }
        
@@ -1859,9 +1889,11 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
                }
                
                if (shi->combinedflag & SCE_PASS_SHADOW)
-                       copy_v3_v3(shr->combined, shr->shad);   /* note, no ';' ! */
+                       copy_v3_v3(shr->diffshad, shr->shad);   /* note, no ';' ! */
                else
-                       copy_v3_v3(shr->combined, shr->diff);
+                       copy_v3_v3(shr->diffshad, shr->diff);
+
+               copy_v3_v3(shr->combined, shr->diffshad);
                        
                /* calculate shadow pass, we use a multiplication mask */
                /* if diff = 0,0,0 it doesn't matter what the shadow pass is, so leave it as is */
@@ -1967,3 +1999,94 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
        shr->combined[3]= shr->alpha;
 }
 
+/* used for "Lamp Data" shader node */
+static float lamp_get_data_internal(ShadeInput *shi, GroupObject *go, float col[4], float lv[3], float *dist, float shadow[4])
+{
+       LampRen *lar = go->lampren;
+       float visifac, inp;
+
+       if (!lar || lar->type == LA_YF_PHOTON
+           || ((lar->mode & LA_LAYER) && (lar->lay & shi->obi->lay) == 0)
+           || (lar->lay & shi->lay) == 0)
+               return 0.0f;
+
+       if (lar->mode & LA_TEXTURE)
+               do_lamp_tex(lar, lv, shi, col, LA_TEXTURE);
+
+       visifac = lamp_get_visibility(lar, shi->co, lv, dist);
+
+       if (visifac == 0.0f
+           || lar->type == LA_HEMI
+           || (lar->type != LA_SPOT && !(lar->mode & LA_SHAD_RAY))
+           || (R.r.scemode & R_BUTS_PREVIEW))
+               return visifac;
+
+       inp = dot_v3v3(shi->vn, lv);
+
+       if (inp > 0.0f) {
+               float shadfac[4];
+
+               shadow[0] = lar->shdwr;
+               shadow[1] = lar->shdwg;
+               shadow[2] = lar->shdwb;
+
+               if (lar->mode & LA_SHAD_TEX)
+                       do_lamp_tex(lar, lv, shi, shadow, LA_SHAD_TEX);
+
+               lamp_get_shadow(lar, shi, inp, shadfac, shi->depth);
+
+               shadow[0] = 1.0f - ((1.0f - shadfac[0] * shadfac[3]) * (1.0f - shadow[0]));
+               shadow[1] = 1.0f - ((1.0f - shadfac[1] * shadfac[3]) * (1.0f - shadow[1]));
+               shadow[2] = 1.0f - ((1.0f - shadfac[2] * shadfac[3]) * (1.0f - shadow[2]));
+       }
+
+       return visifac;
+}
+
+float RE_lamp_get_data(ShadeInput *shi, Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4])
+{
+       col[0] = col[1] = col[2] = 0.0f;
+       col[3] = 1.0f;
+       copy_v3_v3(lv, shi->vn);
+       *dist = 1.0f;
+       shadow[0] = shadow[1] = shadow[2] = shadow[3] = 1.0f;
+
+       if (lamp_obj->type == OB_LAMP) {
+               GroupObject *go;
+               Lamp *lamp = (Lamp *)lamp_obj->data;
+
+               col[0] = lamp->r * lamp->energy;
+               col[1] = lamp->g * lamp->energy;
+               col[2] = lamp->b * lamp->energy;
+
+               if (R.r.scemode & R_BUTS_PREVIEW) {
+                       for (go = R.lights.first; go; go = go->next) {
+                               /* "Lamp.002" is main key light of material preview */
+                               if (strcmp(go->ob->id.name + 2, "Lamp.002") == 0)
+                                       return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
+                       }
+                       return 0.0f;
+               }
+
+               if (shi->light_override) {
+                       for (go = shi->light_override->gobject.first; go; go = go->next) {
+                               if (go->ob == lamp_obj)
+                                       return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
+                       }
+               }
+
+               if (shi->mat && shi->mat->group) {
+                       for (go = shi->mat->group->gobject.first; go; go = go->next) {
+                               if (go->ob == lamp_obj)
+                                       return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
+                       }
+               }
+
+               for (go = R.lights.first; go; go = go->next) {
+                       if (go->ob == lamp_obj)
+                               return lamp_get_data_internal(shi, go, col, lv, dist, shadow);
+               }
+       }
+
+       return 0.0f;
+}