Mesa (master): mesa: do not skip att and spot calculation for infinite light

Yuanhan Liu yliu at kemper.freedesktop.org
Wed Nov 16 03:36:35 UTC 2011


Module: Mesa
Branch: master
Commit: 4f677ca5f9f998a6f57a1390156e772f1f87280a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=4f677ca5f9f998a6f57a1390156e772f1f87280a

Author: Yuanhan Liu <yuanhan.liu at linux.intel.com>
Date:   Wed Nov 16 11:29:08 2011 +0800

mesa: do not skip att and spot calculation for infinite light

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 at linux.intel.com>
Acked-by: Brian Paul <brianp at vmware.com>

---

 src/mesa/main/ffvertex_prog.c |  115 ++++++++++++++++++-----------------------
 1 files changed, 51 insertions(+), 64 deletions(-)

diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c
index 8469078..2c93738 100644
--- a/src/mesa/main/ffvertex_prog.c
+++ b/src/mesa/main/ffvertex_prog.c
@@ -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:




More information about the mesa-commit mailing list