summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYuanhan Liu <[email protected]>2011-11-16 11:29:08 +0800
committerYuanhan Liu <[email protected]>2011-11-16 11:31:04 +0800
commit4f677ca5f9f998a6f57a1390156e772f1f87280a (patch)
tree59483df72a53d054d8261ca29a1cdcc9c03bc98f /src
parent099c4e372df0acb2bda61ccf9e6538b3d8349ea3 (diff)
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 <[email protected]> Acked-by: Brian Paul <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/mesa/main/ffvertex_prog.c113
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: