From 919f57078b289a273e0e46ee2214a9f042b11b1f Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 31 Mar 2009 16:13:14 -0600 Subject: 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. --- src/mesa/main/ffvertex_prog.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/mesa') diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c index 859f72b458..03f42704a7 100644 --- a/src/mesa/main/ffvertex_prog.c +++ b/src/mesa/main/ffvertex_prog.c @@ -1108,6 +1108,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))); @@ -1316,6 +1319,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)) { @@ -1334,8 +1342,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); -- cgit v1.2.3