diff options
-rw-r--r-- | src/mesa/main/ffvertex_prog.c | 113 |
1 files changed, 50 insertions, 63 deletions
diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c index 8469078426b..2c937386a9f 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: |