mesa: do object-space lighting in ffvertex_prog.c
authorKeith Whitwell <keith@tungstengraphics.com>
Fri, 23 May 2008 08:10:59 +0000 (09:10 +0100)
committerKeith Whitwell <keith@tungstengraphics.com>
Fri, 23 May 2008 08:16:58 +0000 (09:16 +0100)
Start pulling over some of the optimizations from the fixed function
paths.

src/mesa/main/ffvertex_prog.c
src/mesa/shader/prog_statevars.c
src/mesa/shader/prog_statevars.h

index 810af9e33e60673ac768e68593d688d10f00af0e..adf15b03c2e7935950d94b2db9dc87091b63a49c 100644 (file)
@@ -54,6 +54,7 @@ struct state_key {
    unsigned light_color_material_mask:12;
    unsigned light_material_mask:12;
 
+   unsigned need_eye_coords:1;
    unsigned normalize:1;
    unsigned rescale_normals:1;
    unsigned fog_source_is_depth:1;
@@ -167,6 +168,8 @@ static struct state_key *make_state_key( GLcontext *ctx )
     */
    assert(fp);
 
+   key->need_eye_coords = ctx->_NeedEyeCoords;
+
    key->fragprog_inputs_read = fp->Base.InputsRead;
 
    if (ctx->RenderMode == GL_FEEDBACK) {
@@ -310,7 +313,7 @@ struct tnl_program {
    
    struct ureg eye_position;
    struct ureg eye_position_normalized;
-   struct ureg eye_normal;
+   struct ureg transformed_normal;
    struct ureg identity;
 
    GLuint materials;
@@ -653,9 +656,9 @@ static void emit_normalize_vec3( struct tnl_program *p,
                                 struct ureg src )
 {
    struct ureg tmp = get_temp(p);
-   emit_op2(p, OPCODE_DP3, tmp, 0, src, src);
-   emit_op1(p, OPCODE_RSQ, tmp, 0, tmp);
-   emit_op2(p, OPCODE_MUL, dest, 0, src, tmp);
+   emit_op2(p, OPCODE_DP3, tmp, WRITEMASK_X, src, src);
+   emit_op1(p, OPCODE_RSQ, tmp, WRITEMASK_X, tmp);
+   emit_op2(p, OPCODE_MUL, dest, 0, src, swizzle1(tmp, X));
    release_temp(p, tmp);
 }
 
@@ -705,36 +708,53 @@ static struct ureg get_eye_position_normalized( struct tnl_program *p )
 }
 
 
-static struct ureg get_eye_normal( struct tnl_program *p )
+static struct ureg get_transformed_normal( struct tnl_program *p )
 {
-   if (is_undef(p->eye_normal)) {
+   if (is_undef(p->transformed_normal) &&
+       !p->state->need_eye_coords &&
+       !p->state->normalize &&
+       !(p->state->need_eye_coords == p->state->rescale_normals))
+   {
+      p->transformed_normal = register_input(p, VERT_ATTRIB_NORMAL );
+   }
+   else if (is_undef(p->transformed_normal)) 
+   {
       struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL );
       struct ureg mvinv[3];
+      struct ureg transformed_normal = reserve_temp(p);
 
-      register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2,
-                             STATE_MATRIX_INVTRANS, mvinv );
+      if (p->state->need_eye_coords) {
+         register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2,
+                                 STATE_MATRIX_INVTRANS, mvinv );
 
-      p->eye_normal = reserve_temp(p);
-
-      /* Transform to eye space:
-       */
-      emit_matrix_transform_vec3( p, p->eye_normal, mvinv, normal );
+         /* Transform to eye space:
+          */
+         emit_matrix_transform_vec3( p, transformed_normal, mvinv, normal );
+         normal = transformed_normal;
+      }
 
       /* Normalize/Rescale:
        */
       if (p->state->normalize) {
-        emit_normalize_vec3( p, p->eye_normal, p->eye_normal );
+        emit_normalize_vec3( p, transformed_normal, normal );
+         normal = transformed_normal;
       }
-      else if (p->state->rescale_normals) {
+      else if (p->state->need_eye_coords == p->state->rescale_normals) {
+         /* This is already adjusted for eye/non-eye rendering:
+          */
         struct ureg rescale = register_param2(p, STATE_INTERNAL,
-                                              STATE_NORMAL_SCALE);
+                                               STATE_NORMAL_SCALE);
 
-        emit_op2( p, OPCODE_MUL, p->eye_normal, 0, p->eye_normal,
+        emit_op2( p, OPCODE_MUL, transformed_normal, 0, normal,
                   swizzle1(rescale, X));
+         normal = transformed_normal;
       }
+      
+      assert(normal.file == PROGRAM_TEMPORARY);
+      p->transformed_normal = normal;
    }
 
-   return p->eye_normal;
+   return p->transformed_normal;
 }
 
 
@@ -856,7 +876,7 @@ static struct ureg calculate_light_attenuation( struct tnl_program *p,
     */
    if (!p->state->unit[i].light_spotcutoff_is_180) {
       struct ureg spot_dir_norm = register_param3(p, STATE_INTERNAL,
-                                                 STATE_SPOT_DIR_NORMALIZED, i);
+                                                 STATE_LIGHT_SPOT_DIR_NORMALIZED, i);
       struct ureg spot = get_temp(p);
       struct ureg slt = get_temp(p);
 
@@ -907,7 +927,7 @@ static void build_lighting( struct tnl_program *p )
    const GLboolean twoside = p->state->light_twoside;
    const GLboolean separate = p->state->separate_specular;
    GLuint nr_lights = 0, count = 0;
-   struct ureg normal = get_eye_normal(p);
+   struct ureg normal = get_transformed_normal(p);
    struct ureg lit = get_temp(p);
    struct ureg dots = get_temp(p);
    struct ureg _col0 = undef, _col1 = undef;
@@ -984,20 +1004,21 @@ static void build_lighting( struct tnl_program *p )
            /* Can used precomputed constants in this case.
             * Attenuation never applies to infinite lights.
             */
-           VPpli = register_param3(p, STATE_LIGHT, i
-                                   STATE_POSITION_NORMALIZED); 
+           VPpli = register_param3(p, STATE_INTERNAL
+                                   STATE_LIGHT_POSITION_NORMALIZED, i); 
             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_LIGHT, i, STATE_HALF_VECTOR);
+                half = register_param3(p, STATE_INTERNAL, 
+                                       STATE_LIGHT_HALF_VECTOR, i);
             }
         } 
         else {
-           struct ureg Ppli = register_param3(p, STATE_LIGHT, i
-                                              STATE_POSITION); 
+           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);
 
@@ -1201,7 +1222,7 @@ static void build_reflect_texgen( struct tnl_program *p,
                                  struct ureg dest,
                                  GLuint writemask )
 {
-   struct ureg normal = get_eye_normal(p);
+   struct ureg normal = get_transformed_normal(p);
    struct ureg eye_hat = get_eye_position_normalized(p);
    struct ureg tmp = get_temp(p);
 
@@ -1219,7 +1240,7 @@ static void build_sphere_texgen( struct tnl_program *p,
                                 struct ureg dest,
                                 GLuint writemask )
 {
-   struct ureg normal = get_eye_normal(p);
+   struct ureg normal = get_transformed_normal(p);
    struct ureg eye_hat = get_eye_position_normalized(p);
    struct ureg tmp = get_temp(p);
    struct ureg half = register_scalar_const(p, .5);
@@ -1338,7 +1359,7 @@ static void build_texture_transform( struct tnl_program *p )
            }
 
            if (normal_mask) {
-              struct ureg normal = get_eye_normal(p);
+              struct ureg normal = get_transformed_normal(p);
               emit_op1(p, OPCODE_MOV, out_texgen, normal_mask, normal );
            }
 
@@ -1475,7 +1496,7 @@ create_new_program( const struct state_key *key,
    p.program = program;
    p.eye_position = undef;
    p.eye_position_normalized = undef;
-   p.eye_normal = undef;
+   p.transformed_normal = undef;
    p.identity = undef;
    p.temp_in_use = 0;
    
index ba3c9884456c75f69eaa2107af93021effc4f0e0..37bd17ba4a0f58051c41109cac1fd4713e5bf30e 100644 (file)
@@ -134,10 +134,6 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
               value[3] = 1.0;
             }                                            
             return;
-        case STATE_POSITION_NORMALIZED:
-            COPY_4V(value, ctx->Light.Light[ln].EyePosition);
-           NORMALIZE_3FV( value );
-            return;
          default:
             _mesa_problem(ctx, "Invalid light state in fetch_state");
             return;
@@ -431,15 +427,46 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
          value[2] = ctx->Fog.Density * ONE_DIV_LN2;
          value[3] = ctx->Fog.Density * ONE_DIV_SQRT_LN2;
          return;
-      case STATE_SPOT_DIR_NORMALIZED: {
+
+      case STATE_LIGHT_SPOT_DIR_NORMALIZED: {
          /* here, state[2] is the light number */
          /* pre-normalize spot dir */
          const GLuint ln = (GLuint) state[2];
-         COPY_3V(value, ctx->Light.Light[ln].EyeDirection);
-         NORMALIZE_3FV(value);
+         COPY_3V(value, ctx->Light.Light[ln]._NormDirection);
          value[3] = ctx->Light.Light[ln]._CosCutoff;
          return;
       }
+
+      case STATE_LIGHT_POSITION: {
+         const GLuint ln = (GLuint) state[2];
+         COPY_4V(value, ctx->Light.Light[ln]._Position);
+         return;
+      }
+
+      case STATE_LIGHT_POSITION_NORMALIZED: {
+         const GLuint ln = (GLuint) state[2];
+         COPY_4V(value, ctx->Light.Light[ln]._Position);
+         NORMALIZE_3FV( value );
+         return;
+      }
+
+      case STATE_LIGHT_HALF_VECTOR: {
+         const GLuint ln = (GLuint) state[2];
+         GLfloat p[3];
+         /* Compute infinite half angle vector:
+          *   halfVector = normalize(normalize(lightPos) + (0, 0, 1))
+          * light.EyePosition.w should be 0 for infinite lights.
+          */
+         COPY_3V(p, ctx->Light.Light[ln]._Position);
+         NORMALIZE_3FV(p);
+         ADD_3V(value, p, ctx->_EyeZDir);
+         NORMALIZE_3FV(value);
+         value[3] = 1.0;
+         return;
+      }                                                  
+
+
+
       case STATE_PT_SCALE:
          value[0] = ctx->Pixel.RedScale;
          value[1] = ctx->Pixel.GreenScale;
@@ -696,7 +723,6 @@ append_token(char *dst, gl_state_index k)
       append(dst, "normalScale");
       break;
    case STATE_INTERNAL:
-   case STATE_POSITION_NORMALIZED:
       append(dst, "(internal)");
       break;
    case STATE_PT_SCALE:
index d12142055fcb178c2889d5183eef74f2437fbfc3..a515fda3aaedfa93c19ce92a8a835e936c639bac 100644 (file)
@@ -106,9 +106,11 @@ typedef enum gl_state_index_ {
    STATE_INTERNAL,             /* Mesa additions */
    STATE_NORMAL_SCALE,
    STATE_TEXRECT_SCALE,
-   STATE_POSITION_NORMALIZED,   /* normalized light position */
    STATE_FOG_PARAMS_OPTIMIZED,  /* for faster fog calc */
-   STATE_SPOT_DIR_NORMALIZED,   /* pre-normalized spot dir */
+   STATE_LIGHT_SPOT_DIR_NORMALIZED,   /* pre-normalized spot dir */
+   STATE_LIGHT_POSITION,              /* object vs eye space */
+   STATE_LIGHT_POSITION_NORMALIZED,   /* object vs eye space */
+   STATE_LIGHT_HALF_VECTOR,           /* object vs eye space */
    STATE_PT_SCALE,              /**< Pixel transfer RGBA scale */
    STATE_PT_BIAS,               /**< Pixel transfer RGBA bias */
    STATE_PCM_SCALE,             /**< Post color matrix RGBA scale */