mesa: do not skip att and spot calculation for infinite light
authorYuanhan Liu <yuanhan.liu@linux.intel.com>
Wed, 16 Nov 2011 03:29:08 +0000 (11:29 +0800)
committerYuanhan Liu <yuanhan.liu@linux.intel.com>
Wed, 16 Nov 2011 03:31:04 +0000 (11:31 +0800)
glspec doesn't say that we should skip the attenuation and spot
calculation for infinite light(Ppli.w == 0). Instead, it gives a same
formula to do the light calculation for both finite light and infinite
light(see page 62 of glspec 2.1.pdf)

Also from the formula (2.4) at page 62 of glspec 2.1.pdf, we can skip
attenuation calculation if Ppli.w == 0.

This would fix all the intel oglc l_sed fail subcases and introduces no
intel oglc regressions.

v2: fix an wrong intendation(comments from Brian).

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Acked-by: Brian Paul <brianp@vmware.com>
src/mesa/main/ffvertex_prog.c

index 8469078426bf8637d4a443afc3bd36b59f021a48..2c937386a9fd1f0a3872b30754ce37638ea6fd46 100644 (file)
@@ -949,7 +949,7 @@ static struct ureg calculate_light_attenuation( struct tnl_program *p,
 {
    struct ureg attenuation = register_param3(p, STATE_LIGHT, i,
                                             STATE_ATTENUATION);
-   struct ureg att = get_temp(p);
+   struct ureg att = undef;
 
    /* Calculate spot attenuation:
     */
@@ -959,6 +959,8 @@ static struct ureg calculate_light_attenuation( struct tnl_program *p,
       struct ureg spot = get_temp(p);
       struct ureg slt = get_temp(p);
 
+      att = get_temp(p);
+
       emit_op2(p, OPCODE_DP3, spot, 0, negate(VPpli), spot_dir_norm);
       emit_op2(p, OPCODE_SLT, slt, 0, swizzle1(spot_dir_norm,W), spot);
       emit_op2(p, OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W));
@@ -968,9 +970,13 @@ static struct ureg calculate_light_attenuation( struct tnl_program *p,
       release_temp(p, slt);
    }
 
-   /* Calculate distance attenuation:
+   /* Calculate distance attenuation(See formula (2.4) at glspec 2.1 page 62):
+    *
+    * Skip the calucation when _dist_ is undefined(light_eyepos3_is_zero)
     */
-   if (p->state->unit[i].light_attenuated) {
+   if (p->state->unit[i].light_attenuated && !is_undef(dist)) {
+      if (is_undef(att))
+         att = get_temp(p);
       /* 1/d,d,d,1/d */
       emit_op1(p, OPCODE_RCP, dist, WRITEMASK_YZ, dist);
       /* 1,d,d*d,1/d */
@@ -1113,73 +1119,54 @@ static void build_lighting( struct tnl_program *p )
       if (p->state->unit[i].light_enabled) {
         struct ureg half = undef;
         struct ureg att = undef, VPpli = undef;
+        struct ureg dist = undef;
 
         count++;
+         if (p->state->unit[i].light_eyepos3_is_zero) {
+             VPpli = register_param3(p, STATE_INTERNAL,
+                                     STATE_LIGHT_POSITION_NORMALIZED, i);
+         } else {
+            struct ureg Ppli = register_param3(p, STATE_INTERNAL,
+                                               STATE_LIGHT_POSITION, i);
+            struct ureg V = get_eye_position(p);
+
+            VPpli = get_temp(p);
+            dist = get_temp(p);
+
+            /* Calculate VPpli vector
+             */
+            emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V);
 
-        if (p->state->unit[i].light_eyepos3_is_zero) {
-           /* Can used precomputed constants in this case.
-            * Attenuation never applies to infinite lights.
-            */
-           VPpli = register_param3(p, STATE_INTERNAL,
-                                   STATE_LIGHT_POSITION_NORMALIZED, i);
-
-            if (!p->state->material_shininess_is_zero) {
-               if (p->state->light_local_viewer) {
-                  struct ureg eye_hat = get_eye_position_normalized(p);
-                  half = get_temp(p);
-                  emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
-                  emit_normalize_vec3(p, half, half);
-               }
-               else {
-                  half = register_param3(p, STATE_INTERNAL,
-                                         STATE_LIGHT_HALF_VECTOR, i);
-               }
-            }
-        }
-        else {
-           struct ureg Ppli = register_param3(p, STATE_INTERNAL,
-                                              STATE_LIGHT_POSITION, i);
-           struct ureg V = get_eye_position(p);
-           struct ureg dist = get_temp(p);
-
-           VPpli = get_temp(p);
-
-           /* Calculate VPpli vector
-            */
-           emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V);
-
-           /* Normalize VPpli.  The dist value also used in
-            * attenuation below.
-            */
-           emit_op2(p, OPCODE_DP3, dist, 0, VPpli, VPpli);
-           emit_op1(p, OPCODE_RSQ, dist, 0, dist);
-           emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist);
-
-           /* Calculate attenuation:
-            */
-           if (!p->state->unit[i].light_spotcutoff_is_180 ||
-               p->state->unit[i].light_attenuated) {
-              att = calculate_light_attenuation(p, i, VPpli, dist);
-           }
-
-           /* Calculate viewer direction, or use infinite viewer:
-            */
-            if (!p->state->material_shininess_is_zero) {
-               half = get_temp(p);
+            /* Normalize VPpli.  The dist value also used in
+             * attenuation below.
+             */
+            emit_op2(p, OPCODE_DP3, dist, 0, VPpli, VPpli);
+            emit_op1(p, OPCODE_RSQ, dist, 0, dist);
+            emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist);
+         }
 
-               if (p->state->light_local_viewer) {
-                  struct ureg eye_hat = get_eye_position_normalized(p);
-                  emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
-               }
-               else {
-                  struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z);
-                  emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir);
-               }
+         /* Calculate attenuation:
+          */
+         att = calculate_light_attenuation(p, i, VPpli, dist);
+         release_temp(p, dist);
 
+        /* Calculate viewer direction, or use infinite viewer:
+         */
+         if (!p->state->material_shininess_is_zero) {
+            if (p->state->light_local_viewer) {
+               struct ureg eye_hat = get_eye_position_normalized(p);
+               half = get_temp(p);
+               emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat);
+               emit_normalize_vec3(p, half, half);
+            } else if (p->state->unit[i].light_eyepos3_is_zero) {
+               half = register_param3(p, STATE_INTERNAL,
+                                      STATE_LIGHT_HALF_VECTOR, i);
+            } else {
+               struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z);
+               half = get_temp(p);
+               emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir);
                emit_normalize_vec3(p, half, half);
             }
-
-           release_temp(p, dist);
         }
 
         /* Calculate dot products: