📄 light.c
字号:
} if (ctx->Light.Model.ColorControl == newenum) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); ctx->Light.Model.ColorControl = newenum; break; default: _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(pname=0x%x)", pname ); break; } if (ctx->Driver.LightModelfv) ctx->Driver.LightModelfv( ctx, pname, params );}void GLAPIENTRY_mesa_LightModeliv( GLenum pname, const GLint *params ){ GLfloat fparam[4]; switch (pname) { case GL_LIGHT_MODEL_AMBIENT: fparam[0] = INT_TO_FLOAT( params[0] ); fparam[1] = INT_TO_FLOAT( params[1] ); fparam[2] = INT_TO_FLOAT( params[2] ); fparam[3] = INT_TO_FLOAT( params[3] ); break; case GL_LIGHT_MODEL_LOCAL_VIEWER: case GL_LIGHT_MODEL_TWO_SIDE: case GL_LIGHT_MODEL_COLOR_CONTROL: fparam[0] = (GLfloat) params[0]; break; default: /* Error will be caught later in gl_LightModelfv */ ; } _mesa_LightModelfv( pname, fparam );}void GLAPIENTRY_mesa_LightModeli( GLenum pname, GLint param ){ _mesa_LightModeliv( pname, ¶m );}void GLAPIENTRY_mesa_LightModelf( GLenum pname, GLfloat param ){ _mesa_LightModelfv( pname, ¶m );}/********** MATERIAL **********//* * Given a face and pname value (ala glColorMaterial), compute a bitmask * of the targeted material values. */GLuint_mesa_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname, GLuint legal, const char *where ){ GLuint bitmask = 0; /* Make a bitmask indicating what material attribute(s) we're updating */ switch (pname) { case GL_EMISSION: bitmask |= MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION; break; case GL_AMBIENT: bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT; break; case GL_DIFFUSE: bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE; break; case GL_SPECULAR: bitmask |= MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR; break; case GL_SHININESS: bitmask |= MAT_BIT_FRONT_SHININESS | MAT_BIT_BACK_SHININESS; break; case GL_AMBIENT_AND_DIFFUSE: bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT; bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE; break; case GL_COLOR_INDEXES: bitmask |= MAT_BIT_FRONT_INDEXES | MAT_BIT_BACK_INDEXES; break; default: _mesa_error( ctx, GL_INVALID_ENUM, where ); return 0; } if (face==GL_FRONT) { bitmask &= FRONT_MATERIAL_BITS; } else if (face==GL_BACK) { bitmask &= BACK_MATERIAL_BITS; } else if (face != GL_FRONT_AND_BACK) { _mesa_error( ctx, GL_INVALID_ENUM, where ); return 0; } if (bitmask & ~legal) { _mesa_error( ctx, GL_INVALID_ENUM, where ); return 0; } return bitmask;}/* Perform a straight copy between materials. */void_mesa_copy_materials( struct gl_material *dst, const struct gl_material *src, GLuint bitmask ){ int i; for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) if (bitmask & (1<<i)) COPY_4FV( dst->Attrib[i], src->Attrib[i] );}/* Update derived values following a change in ctx->Light.Material */void_mesa_update_material( GLcontext *ctx, GLuint bitmask ){ struct gl_light *light, *list = &ctx->Light.EnabledList; GLfloat (*mat)[4] = ctx->Light.Material.Attrib; if (MESA_VERBOSE&VERBOSE_IMMEDIATE) _mesa_debug(ctx, "_mesa_update_material, mask 0x%x\n", bitmask); if (!bitmask) return; /* update material ambience */ if (bitmask & MAT_BIT_FRONT_AMBIENT) { foreach (light, list) { SCALE_3V( light->_MatAmbient[0], light->Ambient, mat[MAT_ATTRIB_FRONT_AMBIENT]); } } if (bitmask & MAT_BIT_BACK_AMBIENT) { foreach (light, list) { SCALE_3V( light->_MatAmbient[1], light->Ambient, mat[MAT_ATTRIB_BACK_AMBIENT]); } } /* update BaseColor = emission + scene's ambience * material's ambience */ if (bitmask & (MAT_BIT_FRONT_EMISSION | MAT_BIT_FRONT_AMBIENT)) { COPY_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_EMISSION] ); ACC_SCALE_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_AMBIENT], ctx->Light.Model.Ambient ); } if (bitmask & (MAT_BIT_BACK_EMISSION | MAT_BIT_BACK_AMBIENT)) { COPY_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_EMISSION] ); ACC_SCALE_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_AMBIENT], ctx->Light.Model.Ambient ); } /* update material diffuse values */ if (bitmask & MAT_BIT_FRONT_DIFFUSE) { foreach (light, list) { SCALE_3V( light->_MatDiffuse[0], light->Diffuse, mat[MAT_ATTRIB_FRONT_DIFFUSE] ); } } if (bitmask & MAT_BIT_BACK_DIFFUSE) { foreach (light, list) { SCALE_3V( light->_MatDiffuse[1], light->Diffuse, mat[MAT_ATTRIB_BACK_DIFFUSE] ); } } /* update material specular values */ if (bitmask & MAT_BIT_FRONT_SPECULAR) { foreach (light, list) { SCALE_3V( light->_MatSpecular[0], light->Specular, mat[MAT_ATTRIB_FRONT_SPECULAR]); } } if (bitmask & MAT_BIT_BACK_SPECULAR) { foreach (light, list) { SCALE_3V( light->_MatSpecular[1], light->Specular, mat[MAT_ATTRIB_BACK_SPECULAR]); } } if (bitmask & MAT_BIT_FRONT_SHININESS) { _mesa_invalidate_shine_table( ctx, 0 ); } if (bitmask & MAT_BIT_BACK_SHININESS) { _mesa_invalidate_shine_table( ctx, 1 ); }}/* * Update the current materials from the given rgba color * according to the bitmask in ColorMaterialBitmask, which is * set by glColorMaterial(). */void_mesa_update_color_material( GLcontext *ctx, const GLfloat color[4] ){ GLuint bitmask = ctx->Light.ColorMaterialBitmask; struct gl_material *mat = &ctx->Light.Material; int i; for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) if (bitmask & (1<<i)) COPY_4FV( mat->Attrib[i], color ); _mesa_update_material( ctx, bitmask );}void GLAPIENTRY_mesa_ColorMaterial( GLenum face, GLenum mode ){ GET_CURRENT_CONTEXT(ctx); GLuint bitmask; GLuint legal = (MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION | MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR | MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE | MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT); ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE&VERBOSE_API) _mesa_debug(ctx, "glColorMaterial %s %s\n", _mesa_lookup_enum_by_nr(face), _mesa_lookup_enum_by_nr(mode)); bitmask = _mesa_material_bitmask(ctx, face, mode, legal, "glColorMaterial"); if (ctx->Light.ColorMaterialBitmask == bitmask && ctx->Light.ColorMaterialFace == face && ctx->Light.ColorMaterialMode == mode) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); ctx->Light.ColorMaterialBitmask = bitmask; ctx->Light.ColorMaterialFace = face; ctx->Light.ColorMaterialMode = mode; if (ctx->Light.ColorMaterialEnabled) { FLUSH_CURRENT( ctx, 0 ); _mesa_update_color_material(ctx,ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); } if (ctx->Driver.ColorMaterial) ctx->Driver.ColorMaterial( ctx, face, mode );}void GLAPIENTRY_mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params ){ GET_CURRENT_CONTEXT(ctx); GLuint f; GLfloat (*mat)[4] = ctx->Light.Material.Attrib; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */ FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */ if (face==GL_FRONT) { f = 0; } else if (face==GL_BACK) { f = 1; } else { _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" ); return; } switch (pname) { case GL_AMBIENT: COPY_4FV( params, mat[MAT_ATTRIB_AMBIENT(f)] ); break; case GL_DIFFUSE: COPY_4FV( params, mat[MAT_ATTRIB_DIFFUSE(f)] ); break; case GL_SPECULAR: COPY_4FV( params, mat[MAT_ATTRIB_SPECULAR(f)] ); break; case GL_EMISSION: COPY_4FV( params, mat[MAT_ATTRIB_EMISSION(f)] ); break; case GL_SHININESS: *params = mat[MAT_ATTRIB_SHININESS(f)][0]; break; case GL_COLOR_INDEXES: params[0] = mat[MAT_ATTRIB_INDEXES(f)][0]; params[1] = mat[MAT_ATTRIB_INDEXES(f)][1]; params[2] = mat[MAT_ATTRIB_INDEXES(f)][2]; break; default: _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" ); }}void GLAPIENTRY_mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params ){ GET_CURRENT_CONTEXT(ctx); GLuint f; GLfloat (*mat)[4] = ctx->Light.Material.Attrib; ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */ FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */ if (face==GL_FRONT) { f = 0; } else if (face==GL_BACK) { f = 1; } else { _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" ); return; } switch (pname) { case GL_AMBIENT: params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][0] ); params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][1] ); params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][2] ); params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][3] ); break; case GL_DIFFUSE: params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][0] ); params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][1] ); params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][2] ); params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][3] ); break; case GL_SPECULAR: params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][0] ); params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][1] ); params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][2] ); params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][3] ); break; case GL_EMISSION: params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][0] ); params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][1] ); params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][2] ); params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][3] ); break; case GL_SHININESS: *params = IROUND( mat[MAT_ATTRIB_SHININESS(f)][0] ); break; case GL_COLOR_INDEXES: params[0] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][0] ); params[1] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][1] ); params[2] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][2] ); break; default: _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" ); }}/**********************************************************************//***** Lighting computation *****//**********************************************************************//* * Notes: * When two-sided lighting is enabled we compute the color (or index) * for both the front and back side of the primitive. Then, when the * orientation of the facet is later learned, we can determine which * color (or index) to use for rendering. * * KW: We now know orientation in advance and only shade for * the side or sides which are actually required. * * Variables: * n = normal vector * V = vertex position * P = light source position * Pe = (0,0,0,1) * * Precomputed: * IF P[3]==0 THEN * // light at infinity * IF local_viewer THEN * _VP_inf_norm = unit vector from V to P // Precompute * ELSE * // eye at infinity * _h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute * ENDIF * ENDIF * * Functions: * Normalize( v ) = normalized vector v * Magnitude( v ) = length of vector v *//* * Whenever the spotlight exponent for a light changes we must call * this function to recompute the exponent lookup table. */void_mesa_invalidate_spot_exp_table( struct gl_light *l ){ l->_SpotExpTable[0][0] = -1;}static voidvalidate_spot_exp_table( struct gl_light *l ){ GLint i; GLdouble exponent = l->SpotExponent; GLdouble tmp = 0; GLint clamp = 0; l->_SpotExpTable[0][0] = 0.0; for (i = EXP_TABLE_SIZE - 1; i > 0 ;i--) { if (clamp == 0) { tmp = _mesa_pow(i / (GLdouble) (EXP_TABLE_SIZE - 1), exponent); if (tmp < FLT_MIN * 100.0) { tmp = 0.0; clamp = 1; } } l->_SpotExpTable[i][0] = (GLfloat) tmp; } for (i = 0; i < EXP_TABLE_SIZE - 1; i++) { l->_SpotExpTable[i][1] = (l->_SpotExpTable[i+1][0] - l->_SpotExpTable[i][0]); } l->_SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;}/* Calculate a new shine table. Doing this here saves a branch in
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -