diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 0348c969bd..c140ed9fc8 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -337,6 +337,6 @@ get_coordinate_system() const { //////////////////////////////////////////////////////////////////// INLINE Light *GraphicsStateGuardian:: get_light(int light_id) const { - nassertr(light_id >= 0 && light_id < _max_lights, (Light *)NULL); + nassertr(light_id >= 0 && light_id < (int)_light_info.size(), (Light *)NULL); return _light_info[light_id]._light; } diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index bb6c70961c..c48fd8d863 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -104,10 +104,6 @@ GraphicsStateGuardian(GraphicsWindow *win) { _coordinate_system = default_coordinate_system; _current_display_region = (DisplayRegion*)0L; _current_lens = (Lens *)NULL; - - _light_info = (LightInfo *)NULL; - _max_lights = 0; - reset(); } @@ -118,7 +114,6 @@ GraphicsStateGuardian(GraphicsWindow *win) { //////////////////////////////////////////////////////////////////// GraphicsStateGuardian:: ~GraphicsStateGuardian() { - init_lights(0); } //////////////////////////////////////////////////////////////////// @@ -421,7 +416,7 @@ begin_frame() { // to be reissued, in case their parameters or positions have // changed between frames. if (_lighting_enabled_this_frame) { - for (int i = 0; i < _max_lights; i++) { + for (int i = 0; i < (int)_light_info.size(); i++) { if (_light_info[i]._enabled) { enable_light(i, false); _light_info[i]._enabled = false; @@ -688,13 +683,14 @@ issue_color(const ColorAttrib *attrib) { // Function: GraphicsStateGuardian::issue_light // Access: Public, Virtual // Description: The default implementation of issue_light() assumes -// we have a limited number of equivalent hardware -// lights available (which were set up by the -// init_lights() call which should have been made in -// reset()). This function assigns each light to a +// we have a limited number of hardware lights +// available. This function assigns each light to a // different hardware light id, trying to keep each // light associated with the same id where possible, but -// reusing id's when necessary. +// reusing id's when necessary. When it is no longer +// possible to reuse existing id's (e.g. all id's are in +// use), slot_light() is called to prepare the next +// sequential light id. // // It will call apply_light() each time a light is // assigned to a particular id for the first time in a @@ -710,17 +706,12 @@ issue_color(const ColorAttrib *attrib) { //////////////////////////////////////////////////////////////////// void GraphicsStateGuardian:: issue_light(const LightAttrib *attrib) { - if (_max_lights == 0) { - // If we don't have any lights configured--no one called - // init_lights()--then forget it. - return; - } - // Initialize the current ambient light total and newly enabled // light list Colorf cur_ambient_light(0.0f, 0.0f, 0.0f, 1.0f); int i; - for (i = 0; i < _max_lights; i++) { + int max_lights = (int)_light_info.size(); + for (i = 0; i < max_lights; i++) { _light_info[i]._next_enabled = false; } @@ -750,7 +741,7 @@ issue_light(const LightAttrib *attrib) { } else { // Check to see if this light has already been bound to an id int cur_light_id = -1; - for (i = 0; i < _max_lights; i++) { + for (i = 0; i < max_lights; i++) { if (_light_info[i]._light == light) { // Light has already been bound to an id, we only need to // enable the light, not reapply it. @@ -764,7 +755,7 @@ issue_light(const LightAttrib *attrib) { // See if there are any unbound light ids if (cur_light_id == -1) { - for (i = 0; i < _max_lights; i++) { + for (i = 0; i < max_lights; i++) { if (_light_info[i]._light == (Light *)NULL) { _light_info[i]._light = light; cur_light_id = i; @@ -776,7 +767,7 @@ issue_light(const LightAttrib *attrib) { // If there were no unbound light ids, see if we can replace // a currently unused but previously bound id if (cur_light_id == -1) { - for (i = 0; i < _max_lights; i++) { + for (i = 0; i < max_lights; i++) { if (!attrib->has_light(_light_info[i]._light)) { _light_info[i]._light = light; cur_light_id = i; @@ -784,6 +775,16 @@ issue_light(const LightAttrib *attrib) { } } } + + // If we *still* don't have a light id, slot a new one. + if (cur_light_id == -1) { + if (slot_new_light(max_lights)) { + cur_light_id = max_lights; + _light_info.push_back(LightInfo()); + max_lights++; + nassertv(max_lights == (int)_light_info.size()); + } + } if (cur_light_id >= 0) { enable_light(cur_light_id, true); @@ -807,7 +808,7 @@ issue_light(const LightAttrib *attrib) { } // Disable all unused lights - for (i = 0; i < _max_lights; i++) { + for (i = 0; i < max_lights; i++) { if (!_light_info[i]._next_enabled) { enable_light(i, false); _light_info[i]._enabled = false; @@ -897,25 +898,21 @@ bind_light(Spotlight *light, int light_id) { } //////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::init_lights -// Access: Protected -// Description: Should be called by a derived class, usually in the -// reset() function, to initialize the table of lights -// according to the number of hardware lights available. -// If the derived class overrides issue_light(), this -// function is not necessary. +// Function: GraphicsStateGuardian::slot_new_light +// Access: Protected, Virtual +// Description: This will be called by the base class before a +// particular light id will be used for the first time. +// It is intended to allow the derived class to reserve +// any additional resources, if required, for the new +// light; and also to indicate whether the hardware +// supports this many simultaneous lights. +// +// The return value should be true if the additional +// light is supported, or false if it is not. //////////////////////////////////////////////////////////////////// -void GraphicsStateGuardian:: -init_lights(int num_lights) { - if (_light_info != (LightInfo *)NULL) { - delete[] _light_info; - _light_info = (LightInfo *)NULL; - } - - _max_lights = num_lights; - if (_max_lights > 0) { - _light_info = new LightInfo[_max_lights]; - } +bool GraphicsStateGuardian:: +slot_new_light(int light_id) { + return true; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index e4f785b0bd..752dab077c 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -155,7 +155,7 @@ public: protected: INLINE Light *get_light(int light_id) const; - void init_lights(int num_lights); + virtual bool slot_new_light(int light_id); virtual void enable_lighting(bool enable); virtual void set_ambient_light(const Colorf &color); virtual void enable_light(int light_id, bool enable); @@ -282,8 +282,7 @@ private: bool _next_enabled; }; - int _max_lights; - LightInfo *_light_info; // LightInfo[_max_lights] + pvector _light_info; bool _lighting_enabled_this_frame; // NOTE: on win32 another DLL (e.g. libpandadx.dll) cannot access diff --git a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx index 309249951d..e52f9fc481 100644 --- a/panda/src/dxgsg/dxGraphicsStateGuardian.cxx +++ b/panda/src/dxgsg/dxGraphicsStateGuardian.cxx @@ -93,11 +93,6 @@ typedef enum { NothingSet=0,NormalOnly,ColorOnly,Normal_Color,TexCoordOnly, #define PER_COLOR ColorOnly #define PER_TEXCOORD TexCoordOnly -// technically DX7's front-end has no limit on the number of lights, but it's simpler for -// this implementation to set a small GL-like limit to make the light array traversals short -// and so I dont have to write code that reallocs light arrays -#define DXGSG_MAX_LIGHTS 8 - static D3DMATRIX matIdentity; #ifdef COUNT_DRAWPRIMS @@ -716,14 +711,6 @@ dx_init( void) { scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); - // technically DX7's front-end has no limit on the number of lights, but it's simpler for - // this implementation to set a small GL-like limit to make the light array traversals short - // and so I dont have to write code that reallocs light arrays - assert((scrn.D3DDevDesc.dwMaxActiveLights==0) || // 0 means infinite lights - (DXGSG_MAX_LIGHTS <= scrn.D3DDevDesc.dwMaxActiveLights)); - - init_lights(DXGSG_MAX_LIGHTS); - if(dx_auto_normalize_lighting) scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS, true); diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index fd72baa488..ce0b5ddd61 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -89,9 +89,6 @@ typedef enum { NothingSet=0,NormalOnly,ColorOnly,Normal_Color,TexCoordOnly, #define PER_COLOR ColorOnly #define PER_TEXCOORD TexCoordOnly -// DX8's SW front-end has no limit on the number of lights, but HW is usually limited to 8 -#define DXGSG_MAX_LIGHTS 8 - // xform mat for vshader will usually be loaded at constant regs c4-c7 #define VSHADER_XFORMMATRIX_CONSTANTREGNUMSTART 4 @@ -773,12 +770,19 @@ dx_init(HCURSOR hMouseCursor) { scrn.pD3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); // Use the diffuse vertex color. + /* + Panda no longer requires us to specify the maximum number of + lights up front, but instead we can define slot_new_light() to + decide one-at-a-time whether a particular light fits within our + limit or not. Until we override this function, there is no + limit. + if(scrn.d3dcaps.MaxActiveLights==0) { // 0 indicates no limit on # of lights, but we use DXGSG_MAX_LIGHTS anyway for now init_lights(DXGSG_MAX_LIGHTS); } else { init_lights(min(DXGSG_MAX_LIGHTS,scrn.d3dcaps.MaxActiveLights)); - } + } */ if(dx_auto_normalize_lighting) scrn.pD3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true); diff --git a/panda/src/glgsg/glGraphicsStateGuardian.cxx b/panda/src/glgsg/glGraphicsStateGuardian.cxx index 660e55c6a2..7491117078 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.cxx +++ b/panda/src/glgsg/glGraphicsStateGuardian.cxx @@ -251,10 +251,10 @@ reset() { glEnable(GL_NORMALIZE); } - // Set up the light id map + // Count the max number of lights GLint max_lights; glGetIntegerv(GL_MAX_LIGHTS, &max_lights); - init_lights(max_lights); + _max_lights = max_lights; // Set up the clip plane id map GLint max_clip_planes; @@ -3347,6 +3347,24 @@ issue_transformed_color(const Colorf &color) const { glColor4fv(transformed.get_data()); } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::slot_new_light +// Access: Protected, Virtual +// Description: This will be called by the base class before a +// particular light id will be used for the first time. +// It is intended to allow the derived class to reserve +// any additional resources, if required, for the new +// light; and also to indicate whether the hardware +// supports this many simultaneous lights. +// +// The return value should be true if the additional +// light is supported, or false if it is not. +//////////////////////////////////////////////////////////////////// +bool GLGraphicsStateGuardian:: +slot_new_light(int light_id) { + return (light_id < _max_lights); +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::enable_lighting // Access: Protected, Virtual diff --git a/panda/src/glgsg/glGraphicsStateGuardian.h b/panda/src/glgsg/glGraphicsStateGuardian.h index e6533f88aa..0a64d5f0d8 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.h +++ b/panda/src/glgsg/glGraphicsStateGuardian.h @@ -146,6 +146,7 @@ public: void issue_transformed_color(const Colorf &color) const; protected: + virtual bool slot_new_light(int light_id); virtual void enable_lighting(bool enable); virtual void set_ambient_light(const Colorf &color); virtual void enable_light(int light_id, bool enable); @@ -305,7 +306,7 @@ protected: bool _polygon_offset_enabled; int _decal_level; - int _cur_light_id; + int _max_lights; LMatrix4f _current_projection_mat; int _projection_mat_stack_count;