summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2009-03-31 16:28:17 -0600
committerBrian Paul <[email protected]>2009-03-31 16:28:17 -0600
commit5b7e9f2f3acb84faab1739bbe370621b7e367cde (patch)
treec690a7ff2355a59e4356a18b4ff7701a9e87ca66
parentd4d4b63d7fa5d72abe6302aa966a0244a6547905 (diff)
mesa: fix bug in GPU codegen for fixed-function two-sided lighting
The 'dots' register wasn't getting properly un-negated and un-swizzled after emitting the code for back-face lighting. So, if more than one light source was enabled, the specular exponent for the next light source was wrong. During execution we were evaluating pow(x, y) where y was negative instead of positive. This led to the outcome being zero or NaN. This fixes the occasional black triangles seen in isosurf when hacked to enable two-sided lighting. (cherry picked from master, commit 919f57078b289a273e0e46ee2214a9f042b11b1f)
-rw-r--r--src/mesa/main/ffvertex_prog.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c
index cc1b44de642..4321b4c2eb3 100644
--- a/src/mesa/main/ffvertex_prog.c
+++ b/src/mesa/main/ffvertex_prog.c
@@ -1104,6 +1104,9 @@ static void build_lighting( struct tnl_program *p )
if (twoside) {
if (!p->state->material_shininess_is_zero) {
+ /* Note that we negate the back-face specular exponent here.
+ * The negation will be un-done later in the back-face code below.
+ */
struct ureg shininess = get_material(p, 1, STATE_SHININESS);
emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z,
negate(swizzle1(shininess,X)));
@@ -1309,6 +1312,11 @@ static void build_lighting( struct tnl_program *p )
mask1 = 0;
}
+ /* For the back face we need to negate the X and Y component
+ * dot products. dots.Z has the negated back-face specular
+ * exponent. We swizzle that into the W position. This
+ * negation makes the back-face specular term positive again.
+ */
dots = negate(swizzle(dots,X,Y,W,Z));
if (!is_undef(att)) {
@@ -1327,8 +1335,10 @@ static void build_lighting( struct tnl_program *p )
emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0);
emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1);
- /* restore negate flag for next lighting */
- dots = negate(dots);
+ /* restore dots to its original state for subsequent lights
+ * by negating and swizzling again.
+ */
+ dots = negate(swizzle(dots,X,Y,W,Z));
release_temp(p, ambient);
release_temp(p, diffuse);