summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2008-05-23 09:10:59 +0100
committerKeith Whitwell <keith@tungstengraphics.com>2008-05-23 09:16:58 +0100
commitadc1f88fc9278bdbb3b24a6d48f91a0bd98e9f1c (patch)
treea3bd2a04eaa12e36d8ab746b9cfcda51b22ef00d
parent7106da136069f865747e03c30ca245bc030b241b (diff)
mesa: do object-space lighting in ffvertex_prog.c
Start pulling over some of the optimizations from the fixed function paths.
-rw-r--r--src/mesa/main/ffvertex_prog.c79
-rw-r--r--src/mesa/shader/prog_statevars.c42
-rw-r--r--src/mesa/shader/prog_statevars.h6
3 files changed, 88 insertions, 39 deletions
diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c
index 810af9e33e..adf15b03c2 100644
--- a/src/mesa/main/ffvertex_prog.c
+++ b/src/mesa/main/ffvertex_prog.c
@@ -54,6 +54,7 @@ struct state_key {
unsigned light_color_material_mask:12;
unsigned light_material_mask:12;
+ unsigned need_eye_coords:1;
unsigned normalize:1;
unsigned rescale_normals:1;
unsigned fog_source_is_depth:1;
@@ -167,6 +168,8 @@ static struct state_key *make_state_key( GLcontext *ctx )
*/
assert(fp);
+ key->need_eye_coords = ctx->_NeedEyeCoords;
+
key->fragprog_inputs_read = fp->Base.InputsRead;
if (ctx->RenderMode == GL_FEEDBACK) {
@@ -310,7 +313,7 @@ struct tnl_program {
struct ureg eye_position;
struct ureg eye_position_normalized;
- struct ureg eye_normal;
+ struct ureg transformed_normal;
struct ureg identity;
GLuint materials;
@@ -653,9 +656,9 @@ static void emit_normalize_vec3( struct tnl_program *p,
struct ureg src )
{
struct ureg tmp = get_temp(p);
- emit_op2(p, OPCODE_DP3, tmp, 0, src, src);
- emit_op1(p, OPCODE_RSQ, tmp, 0, tmp);
- emit_op2(p, OPCODE_MUL, dest, 0, src, tmp);
+ emit_op2(p, OPCODE_DP3, tmp, WRITEMASK_X, src, src);
+ emit_op1(p, OPCODE_RSQ, tmp, WRITEMASK_X, tmp);
+ emit_op2(p, OPCODE_MUL, dest, 0, src, swizzle1(tmp, X));
release_temp(p, tmp);
}
@@ -705,36 +708,53 @@ static struct ureg get_eye_position_normalized( struct tnl_program *p )
}
-static struct ureg get_eye_normal( struct tnl_program *p )
+static struct ureg get_transformed_normal( struct tnl_program *p )
{
- if (is_undef(p->eye_normal)) {
+ if (is_undef(p->transformed_normal) &&
+ !p->state->need_eye_coords &&
+ !p->state->normalize &&
+ !(p->state->need_eye_coords == p->state->rescale_normals))
+ {
+ p->transformed_normal = register_input(p, VERT_ATTRIB_NORMAL );
+ }
+ else if (is_undef(p->transformed_normal))
+ {
struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL );
struct ureg mvinv[3];
+ struct ureg transformed_normal = reserve_temp(p);
- register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2,
- STATE_MATRIX_INVTRANS, mvinv );
+ if (p->state->need_eye_coords) {
+ register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2,
+ STATE_MATRIX_INVTRANS, mvinv );
- p->eye_normal = reserve_temp(p);
-
- /* Transform to eye space:
- */
- emit_matrix_transform_vec3( p, p->eye_normal, mvinv, normal );
+ /* Transform to eye space:
+ */
+ emit_matrix_transform_vec3( p, transformed_normal, mvinv, normal );
+ normal = transformed_normal;
+ }
/* Normalize/Rescale:
*/
if (p->state->normalize) {
- emit_normalize_vec3( p, p->eye_normal, p->eye_normal );
+ emit_normalize_vec3( p, transformed_normal, normal );
+ normal = transformed_normal;
}
- else if (p->state->rescale_normals) {
+ else if (p->state->need_eye_coords == p->state->rescale_normals) {
+ /* This is already adjusted for eye/non-eye rendering:
+ */
struct ureg rescale = register_param2(p, STATE_INTERNAL,
- STATE_NORMAL_SCALE);
+ STATE_NORMAL_SCALE);
- emit_op2( p, OPCODE_MUL, p->eye_normal, 0, p->eye_normal,
+ emit_op2( p, OPCODE_MUL, transformed_normal, 0, normal,
swizzle1(rescale, X));
+ normal = transformed_normal;
}
+
+ assert(normal.file == PROGRAM_TEMPORARY);
+ p->transformed_normal = normal;
}
- return p->eye_normal;
+ return p->transformed_normal;
}
@@ -856,7 +876,7 @@ static struct ureg calculate_light_attenuation( struct tnl_program *p,
*/
if (!p->state->unit[i].light_spotcutoff_is_180) {
struct ureg spot_dir_norm = register_param3(p, STATE_INTERNAL,
- STATE_SPOT_DIR_NORMALIZED, i);
+ STATE_LIGHT_SPOT_DIR_NORMALIZED, i);
struct ureg spot = get_temp(p);
struct ureg slt = get_temp(p);
@@ -907,7 +927,7 @@ static void build_lighting( struct tnl_program *p )
const GLboolean twoside = p->state->light_twoside;
const GLboolean separate = p->state->separate_specular;
GLuint nr_lights = 0, count = 0;
- struct ureg normal = get_eye_normal(p);
+ struct ureg normal = get_transformed_normal(p);
struct ureg lit = get_temp(p);
struct ureg dots = get_temp(p);
struct ureg _col0 = undef, _col1 = undef;
@@ -984,20 +1004,21 @@ static void build_lighting( struct tnl_program *p )
/* Can used precomputed constants in this case.
* Attenuation never applies to infinite lights.
*/
- VPpli = register_param3(p, STATE_LIGHT, i,
- STATE_POSITION_NORMALIZED);
+ VPpli = register_param3(p, STATE_INTERNAL,
+ STATE_LIGHT_POSITION_NORMALIZED, i);
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_LIGHT, i, STATE_HALF_VECTOR);
+ half = register_param3(p, STATE_INTERNAL,
+ STATE_LIGHT_HALF_VECTOR, i);
}
}
else {
- struct ureg Ppli = register_param3(p, STATE_LIGHT, i,
- STATE_POSITION);
+ 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);
@@ -1201,7 +1222,7 @@ static void build_reflect_texgen( struct tnl_program *p,
struct ureg dest,
GLuint writemask )
{
- struct ureg normal = get_eye_normal(p);
+ struct ureg normal = get_transformed_normal(p);
struct ureg eye_hat = get_eye_position_normalized(p);
struct ureg tmp = get_temp(p);
@@ -1219,7 +1240,7 @@ static void build_sphere_texgen( struct tnl_program *p,
struct ureg dest,
GLuint writemask )
{
- struct ureg normal = get_eye_normal(p);
+ struct ureg normal = get_transformed_normal(p);
struct ureg eye_hat = get_eye_position_normalized(p);
struct ureg tmp = get_temp(p);
struct ureg half = register_scalar_const(p, .5);
@@ -1338,7 +1359,7 @@ static void build_texture_transform( struct tnl_program *p )
}
if (normal_mask) {
- struct ureg normal = get_eye_normal(p);
+ struct ureg normal = get_transformed_normal(p);
emit_op1(p, OPCODE_MOV, out_texgen, normal_mask, normal );
}
@@ -1475,7 +1496,7 @@ create_new_program( const struct state_key *key,
p.program = program;
p.eye_position = undef;
p.eye_position_normalized = undef;
- p.eye_normal = undef;
+ p.transformed_normal = undef;
p.identity = undef;
p.temp_in_use = 0;
diff --git a/src/mesa/shader/prog_statevars.c b/src/mesa/shader/prog_statevars.c
index ba3c988445..37bd17ba4a 100644
--- a/src/mesa/shader/prog_statevars.c
+++ b/src/mesa/shader/prog_statevars.c
@@ -134,10 +134,6 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
value[3] = 1.0;
}
return;
- case STATE_POSITION_NORMALIZED:
- COPY_4V(value, ctx->Light.Light[ln].EyePosition);
- NORMALIZE_3FV( value );
- return;
default:
_mesa_problem(ctx, "Invalid light state in fetch_state");
return;
@@ -431,15 +427,46 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
value[2] = ctx->Fog.Density * ONE_DIV_LN2;
value[3] = ctx->Fog.Density * ONE_DIV_SQRT_LN2;
return;
- case STATE_SPOT_DIR_NORMALIZED: {
+
+ case STATE_LIGHT_SPOT_DIR_NORMALIZED: {
/* here, state[2] is the light number */
/* pre-normalize spot dir */
const GLuint ln = (GLuint) state[2];
- COPY_3V(value, ctx->Light.Light[ln].EyeDirection);
- NORMALIZE_3FV(value);
+ COPY_3V(value, ctx->Light.Light[ln]._NormDirection);
value[3] = ctx->Light.Light[ln]._CosCutoff;
return;
}
+
+ case STATE_LIGHT_POSITION: {
+ const GLuint ln = (GLuint) state[2];
+ COPY_4V(value, ctx->Light.Light[ln]._Position);
+ return;
+ }
+
+ case STATE_LIGHT_POSITION_NORMALIZED: {
+ const GLuint ln = (GLuint) state[2];
+ COPY_4V(value, ctx->Light.Light[ln]._Position);
+ NORMALIZE_3FV( value );
+ return;
+ }
+
+ case STATE_LIGHT_HALF_VECTOR: {
+ const GLuint ln = (GLuint) state[2];
+ GLfloat p[3];
+ /* Compute infinite half angle vector:
+ * halfVector = normalize(normalize(lightPos) + (0, 0, 1))
+ * light.EyePosition.w should be 0 for infinite lights.
+ */
+ COPY_3V(p, ctx->Light.Light[ln]._Position);
+ NORMALIZE_3FV(p);
+ ADD_3V(value, p, ctx->_EyeZDir);
+ NORMALIZE_3FV(value);
+ value[3] = 1.0;
+ return;
+ }
+
+
+
case STATE_PT_SCALE:
value[0] = ctx->Pixel.RedScale;
value[1] = ctx->Pixel.GreenScale;
@@ -696,7 +723,6 @@ append_token(char *dst, gl_state_index k)
append(dst, "normalScale");
break;
case STATE_INTERNAL:
- case STATE_POSITION_NORMALIZED:
append(dst, "(internal)");
break;
case STATE_PT_SCALE:
diff --git a/src/mesa/shader/prog_statevars.h b/src/mesa/shader/prog_statevars.h
index d12142055f..a515fda3aa 100644
--- a/src/mesa/shader/prog_statevars.h
+++ b/src/mesa/shader/prog_statevars.h
@@ -106,9 +106,11 @@ typedef enum gl_state_index_ {
STATE_INTERNAL, /* Mesa additions */
STATE_NORMAL_SCALE,
STATE_TEXRECT_SCALE,
- STATE_POSITION_NORMALIZED, /* normalized light position */
STATE_FOG_PARAMS_OPTIMIZED, /* for faster fog calc */
- STATE_SPOT_DIR_NORMALIZED, /* pre-normalized spot dir */
+ STATE_LIGHT_SPOT_DIR_NORMALIZED, /* pre-normalized spot dir */
+ STATE_LIGHT_POSITION, /* object vs eye space */
+ STATE_LIGHT_POSITION_NORMALIZED, /* object vs eye space */
+ STATE_LIGHT_HALF_VECTOR, /* object vs eye space */
STATE_PT_SCALE, /**< Pixel transfer RGBA scale */
STATE_PT_BIAS, /**< Pixel transfer RGBA bias */
STATE_PCM_SCALE, /**< Post color matrix RGBA scale */