summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2008-06-12 11:17:20 -0600
committerBrian Paul <[email protected]>2008-06-12 11:17:46 -0600
commit5ecb2f2d0fca0c5ea847d1968459aa0dd8138f14 (patch)
treee4cf3312eeb2d2d73f45b1a13fa5166c5af20dab
parent23d340c9edbbe64a99478b922c008ae3e2ec7103 (diff)
mesa: restore and fix Keith's "further degenerate the special case lit substitute"
There was a bug in emit_degenerate_lit() that caused the SLT to produce unpredictable results in lit.z Plus, added a bunch of new comments.
-rw-r--r--src/mesa/main/ffvertex_prog.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c
index d71e0c00fdb..e6c7c1040fa 100644
--- a/src/mesa/main/ffvertex_prog.c
+++ b/src/mesa/main/ffvertex_prog.c
@@ -969,25 +969,29 @@ static struct ureg calculate_light_attenuation( struct tnl_program *p,
}
+/**
+ * Compute:
+ * lit.y = MAX(0, dots.x)
+ * lit.z = SLT(0, dots.x)
+ */
static void emit_degenerate_lit( struct tnl_program *p,
struct ureg lit,
struct ureg dots )
{
- struct ureg id = get_identity_param(p);
-
- /* 1, 0, 0, 1
+ struct ureg id = get_identity_param(p); /* id = {0,0,0,1} */
+
+ /* Note that lit.x & lit.w will not be examined. Note also that
+ * dots.xyzw == dots.xxxx.
*/
- emit_op1(p, OPCODE_MOV, lit, 0, swizzle(id, Z, X, X, Z));
- /* 1, MAX2(in[0], 0), 0, 1
+ /* MAX lit, id, dots;
*/
- emit_op2(p, OPCODE_MAX, lit, WRITEMASK_Y, lit, swizzle1(dots, X));
+ emit_op2(p, OPCODE_MAX, lit, WRITEMASK_XYZW, id, dots);
- /* 1, MAX2(in[0], 0), (in[0] > 0 ? 1 : 0), 1
+ /* result[2] = (in > 0 ? 1 : 0)
+ * SLT lit.z, id.z, dots; # lit.z = (0 < dots.z) ? 1 : 0
*/
- emit_op2(p, OPCODE_SLT, lit, WRITEMASK_Z,
- lit, /* 0 */
- swizzle1(dots, X)); /* in[0] */
+ emit_op2(p, OPCODE_SLT, lit, WRITEMASK_Z, swizzle1(id,Z), dots);
}
@@ -1007,6 +1011,14 @@ static void build_lighting( struct tnl_program *p )
struct ureg _bfc0 = undef, _bfc1 = undef;
GLuint i;
+ /*
+ * NOTE:
+ * dot.x = dot(normal, VPpli)
+ * dot.y = dot(normal, halfAngle)
+ * dot.z = back.shininess
+ * dot.w = front.shininess
+ */
+
for (i = 0; i < MAX_LIGHTS; i++)
if (p->state->unit[i].light_enabled)
nr_lights++;
@@ -1144,10 +1156,13 @@ static void build_lighting( struct tnl_program *p )
/* Calculate dot products:
*/
- emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli);
-
- if (!p->state->material_shininess_is_zero)
+ if (p->state->material_shininess_is_zero) {
+ emit_op2(p, OPCODE_DP3, dots, 0, normal, VPpli);
+ }
+ else {
+ emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli);
emit_op2(p, OPCODE_DP3, dots, WRITEMASK_Y, normal, half);
+ }
/* Front face lighting:
*/
@@ -1181,15 +1196,18 @@ static void build_lighting( struct tnl_program *p )
if (!is_undef(att)) {
+ /* light is attenuated by distance */
emit_op1(p, OPCODE_LIT, lit, 0, dots);
emit_op2(p, OPCODE_MUL, lit, 0, lit, att);
emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0);
}
else if (!p->state->material_shininess_is_zero) {
+ /* there's a non-zero specular term */
emit_op1(p, OPCODE_LIT, lit, 0, dots);
emit_op2(p, OPCODE_ADD, _col0, 0, ambient, _col0);
}
else {
+ /* no attenutation, no specular */
emit_degenerate_lit(p, lit, dots);
emit_op2(p, OPCODE_ADD, _col0, 0, ambient, _col0);
}