📄 light.c
字号:
/* * Mesa 3-D graphics library * Version: 7.0 * * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */#include "glheader.h"#include "imports.h"#include "context.h"#include "enums.h"#include "light.h"#include "macros.h"#include "simple_list.h"#include "mtypes.h"#include "math/m_matrix.h"void GLAPIENTRY_mesa_ShadeModel( GLenum mode ){ GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glShadeModel %s\n", _mesa_lookup_enum_by_nr(mode)); if (mode != GL_FLAT && mode != GL_SMOOTH) { _mesa_error(ctx, GL_INVALID_ENUM, "glShadeModel"); return; } if (ctx->Light.ShadeModel == mode) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); ctx->Light.ShadeModel = mode; if (mode == GL_FLAT) ctx->_TriangleCaps |= DD_FLATSHADE; else ctx->_TriangleCaps &= ~DD_FLATSHADE; if (ctx->Driver.ShadeModel) ctx->Driver.ShadeModel( ctx, mode );}/** * Helper function called by _mesa_Lightfv and _mesa_PopAttrib to set * per-light state. * For GL_POSITION and GL_SPOT_DIRECTION the params position/direction * will have already been transformed by the modelview matrix! * Also, all error checking should have already been done. */void_mesa_light(GLcontext *ctx, GLuint lnum, GLenum pname, const GLfloat *params){ struct gl_light *light; ASSERT(lnum < MAX_LIGHTS); light = &ctx->Light.Light[lnum]; switch (pname) { case GL_AMBIENT: if (TEST_EQ_4V(light->Ambient, params)) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); COPY_4V( light->Ambient, params ); break; case GL_DIFFUSE: if (TEST_EQ_4V(light->Diffuse, params)) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); COPY_4V( light->Diffuse, params ); break; case GL_SPECULAR: if (TEST_EQ_4V(light->Specular, params)) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); COPY_4V( light->Specular, params ); break; case GL_POSITION: /* NOTE: position has already been transformed by ModelView! */ if (TEST_EQ_4V(light->EyePosition, params)) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); COPY_4V(light->EyePosition, params); if (light->EyePosition[3] != 0.0F) light->_Flags |= LIGHT_POSITIONAL; else light->_Flags &= ~LIGHT_POSITIONAL; break; case GL_SPOT_DIRECTION: /* NOTE: Direction already transformed by inverse ModelView! */ if (TEST_EQ_3V(light->EyeDirection, params)) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); COPY_3V(light->EyeDirection, params); break; case GL_SPOT_EXPONENT: ASSERT(params[0] >= 0.0); ASSERT(params[0] <= ctx->Const.MaxSpotExponent); if (light->SpotExponent == params[0]) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); light->SpotExponent = params[0]; _mesa_invalidate_spot_exp_table(light); break; case GL_SPOT_CUTOFF: ASSERT(params[0] == 180.0 || (params[0] >= 0.0 && params[0] <= 90.0)); if (light->SpotCutoff == params[0]) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); light->SpotCutoff = params[0]; light->_CosCutoffNeg = (GLfloat) (_mesa_cos(light->SpotCutoff * DEG2RAD)); if (light->_CosCutoffNeg < 0) light->_CosCutoff = 0; else light->_CosCutoff = light->_CosCutoffNeg; if (light->SpotCutoff != 180.0F) light->_Flags |= LIGHT_SPOT; else light->_Flags &= ~LIGHT_SPOT; break; case GL_CONSTANT_ATTENUATION: ASSERT(params[0] >= 0.0); if (light->ConstantAttenuation == params[0]) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); light->ConstantAttenuation = params[0]; break; case GL_LINEAR_ATTENUATION: ASSERT(params[0] >= 0.0); if (light->LinearAttenuation == params[0]) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); light->LinearAttenuation = params[0]; break; case GL_QUADRATIC_ATTENUATION: ASSERT(params[0] >= 0.0); if (light->QuadraticAttenuation == params[0]) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); light->QuadraticAttenuation = params[0]; break; default: _mesa_problem(ctx, "Unexpected pname in _mesa_light()"); return; } if (ctx->Driver.Lightfv) ctx->Driver.Lightfv( ctx, GL_LIGHT0 + lnum, pname, params );}void GLAPIENTRY_mesa_Lightf( GLenum light, GLenum pname, GLfloat param ){ _mesa_Lightfv( light, pname, ¶m );}void GLAPIENTRY_mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params ){ GET_CURRENT_CONTEXT(ctx); GLint i = (GLint) (light - GL_LIGHT0); GLfloat temp[4]; ASSERT_OUTSIDE_BEGIN_END(ctx); if (i < 0 || i >= (GLint) ctx->Const.MaxLights) { _mesa_error( ctx, GL_INVALID_ENUM, "glLight(light=0x%x)", light ); return; } /* do particular error checks, transformations */ switch (pname) { case GL_AMBIENT: case GL_DIFFUSE: case GL_SPECULAR: /* nothing */ break; case GL_POSITION: /* transform position by ModelView matrix */ TRANSFORM_POINT(temp, ctx->ModelviewMatrixStack.Top->m, params); params = temp; break; case GL_SPOT_DIRECTION: /* transform direction by inverse modelview */ if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) { _math_matrix_analyse(ctx->ModelviewMatrixStack.Top); } TRANSFORM_NORMAL(temp, params, ctx->ModelviewMatrixStack.Top->inv); params = temp; break; case GL_SPOT_EXPONENT: if (params[0] < 0.0 || params[0] > ctx->Const.MaxSpotExponent) { _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); return; } break; case GL_SPOT_CUTOFF: if ((params[0] < 0.0 || params[0] > 90.0) && params[0] != 180.0) { _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); return; } break; case GL_CONSTANT_ATTENUATION: if (params[0] < 0.0) { _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); return; } break; case GL_LINEAR_ATTENUATION: if (params[0] < 0.0) { _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); return; } break; case GL_QUADRATIC_ATTENUATION: if (params[0] < 0.0) { _mesa_error(ctx, GL_INVALID_VALUE, "glLight"); return; } break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glLight(pname=0x%x)", pname); return; } _mesa_light(ctx, i, pname, params);}void GLAPIENTRY_mesa_Lighti( GLenum light, GLenum pname, GLint param ){ _mesa_Lightiv( light, pname, ¶m );}void GLAPIENTRY_mesa_Lightiv( GLenum light, GLenum pname, const GLint *params ){ GLfloat fparam[4]; switch (pname) { case GL_AMBIENT: case GL_DIFFUSE: case GL_SPECULAR: 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_POSITION: fparam[0] = (GLfloat) params[0]; fparam[1] = (GLfloat) params[1]; fparam[2] = (GLfloat) params[2]; fparam[3] = (GLfloat) params[3]; break; case GL_SPOT_DIRECTION: fparam[0] = (GLfloat) params[0]; fparam[1] = (GLfloat) params[1]; fparam[2] = (GLfloat) params[2]; break; case GL_SPOT_EXPONENT: case GL_SPOT_CUTOFF: case GL_CONSTANT_ATTENUATION: case GL_LINEAR_ATTENUATION: case GL_QUADRATIC_ATTENUATION: fparam[0] = (GLfloat) params[0]; break; default: /* error will be caught later in gl_Lightfv */ ; } _mesa_Lightfv( light, pname, fparam );}void GLAPIENTRY_mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params ){ GET_CURRENT_CONTEXT(ctx); GLint l = (GLint) (light - GL_LIGHT0); ASSERT_OUTSIDE_BEGIN_END(ctx); if (l < 0 || l >= (GLint) ctx->Const.MaxLights) { _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" ); return; } switch (pname) { case GL_AMBIENT: COPY_4V( params, ctx->Light.Light[l].Ambient ); break; case GL_DIFFUSE: COPY_4V( params, ctx->Light.Light[l].Diffuse ); break; case GL_SPECULAR: COPY_4V( params, ctx->Light.Light[l].Specular ); break; case GL_POSITION: COPY_4V( params, ctx->Light.Light[l].EyePosition ); break; case GL_SPOT_DIRECTION: COPY_3V( params, ctx->Light.Light[l].EyeDirection ); break; case GL_SPOT_EXPONENT: params[0] = ctx->Light.Light[l].SpotExponent; break; case GL_SPOT_CUTOFF: params[0] = ctx->Light.Light[l].SpotCutoff; break; case GL_CONSTANT_ATTENUATION: params[0] = ctx->Light.Light[l].ConstantAttenuation; break; case GL_LINEAR_ATTENUATION: params[0] = ctx->Light.Light[l].LinearAttenuation; break; case GL_QUADRATIC_ATTENUATION: params[0] = ctx->Light.Light[l].QuadraticAttenuation; break; default: _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" ); break; }}void GLAPIENTRY_mesa_GetLightiv( GLenum light, GLenum pname, GLint *params ){ GET_CURRENT_CONTEXT(ctx); GLint l = (GLint) (light - GL_LIGHT0); ASSERT_OUTSIDE_BEGIN_END(ctx); if (l < 0 || l >= (GLint) ctx->Const.MaxLights) { _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" ); return; } switch (pname) { case GL_AMBIENT: params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]); params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]); params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]); params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]); break; case GL_DIFFUSE: params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]); params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]); params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]); params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]); break; case GL_SPECULAR: params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]); params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]); params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]); params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]); break; case GL_POSITION: params[0] = (GLint) ctx->Light.Light[l].EyePosition[0]; params[1] = (GLint) ctx->Light.Light[l].EyePosition[1]; params[2] = (GLint) ctx->Light.Light[l].EyePosition[2]; params[3] = (GLint) ctx->Light.Light[l].EyePosition[3]; break; case GL_SPOT_DIRECTION: params[0] = (GLint) ctx->Light.Light[l].EyeDirection[0]; params[1] = (GLint) ctx->Light.Light[l].EyeDirection[1]; params[2] = (GLint) ctx->Light.Light[l].EyeDirection[2]; break; case GL_SPOT_EXPONENT: params[0] = (GLint) ctx->Light.Light[l].SpotExponent; break; case GL_SPOT_CUTOFF: params[0] = (GLint) ctx->Light.Light[l].SpotCutoff; break; case GL_CONSTANT_ATTENUATION: params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation; break; case GL_LINEAR_ATTENUATION: params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation; break; case GL_QUADRATIC_ATTENUATION: params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation; break; default: _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" ); break; }}/**********************************************************************//*** Light Model ***//**********************************************************************/void GLAPIENTRY_mesa_LightModelfv( GLenum pname, const GLfloat *params ){ GLenum newenum; GLboolean newbool; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); switch (pname) { case GL_LIGHT_MODEL_AMBIENT: if (TEST_EQ_4V( ctx->Light.Model.Ambient, params )) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); COPY_4V( ctx->Light.Model.Ambient, params ); break; case GL_LIGHT_MODEL_LOCAL_VIEWER: newbool = (params[0]!=0.0); if (ctx->Light.Model.LocalViewer == newbool) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); ctx->Light.Model.LocalViewer = newbool; break; case GL_LIGHT_MODEL_TWO_SIDE: newbool = (params[0]!=0.0); if (ctx->Light.Model.TwoSide == newbool) return; FLUSH_VERTICES(ctx, _NEW_LIGHT); ctx->Light.Model.TwoSide = newbool; if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE; else ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE; break; case GL_LIGHT_MODEL_COLOR_CONTROL: if (params[0] == (GLfloat) GL_SINGLE_COLOR) newenum = GL_SINGLE_COLOR; else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR) newenum = GL_SEPARATE_SPECULAR_COLOR; else { _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(param=0x0%x)", (GLint) params[0] ); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -