Browse Source

don't expect a fixed number of lights

David Rose 23 years ago
parent
commit
ab97742881

+ 1 - 1
panda/src/display/graphicsStateGuardian.I

@@ -337,6 +337,6 @@ get_coordinate_system() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE Light *GraphicsStateGuardian::
 INLINE Light *GraphicsStateGuardian::
 get_light(int light_id) const {
 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;
   return _light_info[light_id]._light;
 }
 }

+ 37 - 40
panda/src/display/graphicsStateGuardian.cxx

@@ -104,10 +104,6 @@ GraphicsStateGuardian(GraphicsWindow *win) {
   _coordinate_system = default_coordinate_system;
   _coordinate_system = default_coordinate_system;
   _current_display_region = (DisplayRegion*)0L;
   _current_display_region = (DisplayRegion*)0L;
   _current_lens = (Lens *)NULL;
   _current_lens = (Lens *)NULL;
-
-  _light_info = (LightInfo *)NULL;
-  _max_lights = 0;
-
   reset();
   reset();
 }
 }
 
 
@@ -118,7 +114,6 @@ GraphicsStateGuardian(GraphicsWindow *win) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 GraphicsStateGuardian::
 GraphicsStateGuardian::
 ~GraphicsStateGuardian() {
 ~GraphicsStateGuardian() {
-  init_lights(0);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -421,7 +416,7 @@ begin_frame() {
   // to be reissued, in case their parameters or positions have
   // to be reissued, in case their parameters or positions have
   // changed between frames.
   // changed between frames.
   if (_lighting_enabled_this_frame) {
   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) {
       if (_light_info[i]._enabled) {
         enable_light(i, false);
         enable_light(i, false);
         _light_info[i]._enabled = false;
         _light_info[i]._enabled = false;
@@ -688,13 +683,14 @@ issue_color(const ColorAttrib *attrib) {
 //     Function: GraphicsStateGuardian::issue_light
 //     Function: GraphicsStateGuardian::issue_light
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description: The default implementation of issue_light() assumes
 //  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
 //               different hardware light id, trying to keep each
 //               light associated with the same id where possible, but
 //               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
 //               It will call apply_light() each time a light is
 //               assigned to a particular id for the first time in a
 //               assigned to a particular id for the first time in a
@@ -710,17 +706,12 @@ issue_color(const ColorAttrib *attrib) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
 void GraphicsStateGuardian::
 issue_light(const LightAttrib *attrib) {
 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
   // Initialize the current ambient light total and newly enabled
   // light list
   // light list
   Colorf cur_ambient_light(0.0f, 0.0f, 0.0f, 1.0f);
   Colorf cur_ambient_light(0.0f, 0.0f, 0.0f, 1.0f);
   int i;
   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;
     _light_info[i]._next_enabled = false;
   }
   }
 
 
@@ -750,7 +741,7 @@ issue_light(const LightAttrib *attrib) {
     } else {
     } else {
       // Check to see if this light has already been bound to an id
       // Check to see if this light has already been bound to an id
       int cur_light_id = -1;
       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) {
         if (_light_info[i]._light == light) {
           // Light has already been bound to an id, we only need to
           // Light has already been bound to an id, we only need to
           // enable the light, not reapply it.
           // enable the light, not reapply it.
@@ -764,7 +755,7 @@ issue_light(const LightAttrib *attrib) {
         
         
       // See if there are any unbound light ids
       // See if there are any unbound light ids
       if (cur_light_id == -1) {
       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) {
           if (_light_info[i]._light == (Light *)NULL) {
             _light_info[i]._light = light;
             _light_info[i]._light = light;
             cur_light_id = i;
             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
       // If there were no unbound light ids, see if we can replace
       // a currently unused but previously bound id
       // a currently unused but previously bound id
       if (cur_light_id == -1) {
       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)) {
           if (!attrib->has_light(_light_info[i]._light)) {
             _light_info[i]._light = light;
             _light_info[i]._light = light;
             cur_light_id = i;
             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) {
       if (cur_light_id >= 0) {
         enable_light(cur_light_id, true);
         enable_light(cur_light_id, true);
@@ -807,7 +808,7 @@ issue_light(const LightAttrib *attrib) {
   }
   }
 
 
   // Disable all unused lights
   // Disable all unused lights
-  for (i = 0; i < _max_lights; i++) {
+  for (i = 0; i < max_lights; i++) {
     if (!_light_info[i]._next_enabled) {
     if (!_light_info[i]._next_enabled) {
       enable_light(i, false);
       enable_light(i, false);
       _light_info[i]._enabled = 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;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 3
panda/src/display/graphicsStateGuardian.h

@@ -155,7 +155,7 @@ public:
 
 
 protected:
 protected:
   INLINE Light *get_light(int light_id) const;
   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 enable_lighting(bool enable);
   virtual void set_ambient_light(const Colorf &color);
   virtual void set_ambient_light(const Colorf &color);
   virtual void enable_light(int light_id, bool enable);
   virtual void enable_light(int light_id, bool enable);
@@ -282,8 +282,7 @@ private:
     bool _next_enabled;
     bool _next_enabled;
   };
   };
 
 
-  int _max_lights;
-  LightInfo *_light_info;          // LightInfo[_max_lights]
+  pvector<LightInfo> _light_info;
   bool _lighting_enabled_this_frame;
   bool _lighting_enabled_this_frame;
 
 
   // NOTE: on win32 another DLL (e.g. libpandadx.dll) cannot access
   // NOTE: on win32 another DLL (e.g. libpandadx.dll) cannot access

+ 0 - 13
panda/src/dxgsg/dxGraphicsStateGuardian.cxx

@@ -93,11 +93,6 @@ typedef enum { NothingSet=0,NormalOnly,ColorOnly,Normal_Color,TexCoordOnly,
 #define PER_COLOR    ColorOnly
 #define PER_COLOR    ColorOnly
 #define PER_TEXCOORD TexCoordOnly
 #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;
 static D3DMATRIX matIdentity;
 
 
 #ifdef COUNT_DRAWPRIMS
 #ifdef COUNT_DRAWPRIMS
@@ -716,14 +711,6 @@ dx_init( void) {
 
 
     scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1);
     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)
     if(dx_auto_normalize_lighting)
          scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS, true);
          scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS, true);
 
 

+ 8 - 4
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -89,9 +89,6 @@ typedef enum { NothingSet=0,NormalOnly,ColorOnly,Normal_Color,TexCoordOnly,
 #define PER_COLOR    ColorOnly
 #define PER_COLOR    ColorOnly
 #define PER_TEXCOORD TexCoordOnly
 #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
 // xform mat for vshader will usually be loaded at constant regs c4-c7
 #define VSHADER_XFORMMATRIX_CONSTANTREGNUMSTART 4
 #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. 
     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) {  
     if(scrn.d3dcaps.MaxActiveLights==0) {  
         // 0 indicates no limit on # of lights, but we use DXGSG_MAX_LIGHTS anyway for now
         // 0 indicates no limit on # of lights, but we use DXGSG_MAX_LIGHTS anyway for now
       init_lights(DXGSG_MAX_LIGHTS);
       init_lights(DXGSG_MAX_LIGHTS);
     } else {
     } else {
       init_lights(min(DXGSG_MAX_LIGHTS,scrn.d3dcaps.MaxActiveLights));
       init_lights(min(DXGSG_MAX_LIGHTS,scrn.d3dcaps.MaxActiveLights));
-    }
+    } */
 
 
     if(dx_auto_normalize_lighting)
     if(dx_auto_normalize_lighting)
          scrn.pD3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);
          scrn.pD3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);

+ 20 - 2
panda/src/glgsg/glGraphicsStateGuardian.cxx

@@ -251,10 +251,10 @@ reset() {
     glEnable(GL_NORMALIZE);
     glEnable(GL_NORMALIZE);
   }
   }
 
 
-  // Set up the light id map
+  // Count the max number of lights
   GLint max_lights;
   GLint max_lights;
   glGetIntegerv(GL_MAX_LIGHTS, &max_lights);
   glGetIntegerv(GL_MAX_LIGHTS, &max_lights);
-  init_lights(max_lights);
+  _max_lights = max_lights;
 
 
   // Set up the clip plane id map
   // Set up the clip plane id map
   GLint max_clip_planes;
   GLint max_clip_planes;
@@ -3347,6 +3347,24 @@ issue_transformed_color(const Colorf &color) const {
   glColor4fv(transformed.get_data());
   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
 //     Function: GLGraphicsStateGuardian::enable_lighting
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual

+ 2 - 1
panda/src/glgsg/glGraphicsStateGuardian.h

@@ -146,6 +146,7 @@ public:
   void issue_transformed_color(const Colorf &color) const;
   void issue_transformed_color(const Colorf &color) const;
 
 
 protected:
 protected:
+  virtual bool slot_new_light(int light_id);
   virtual void enable_lighting(bool enable);
   virtual void enable_lighting(bool enable);
   virtual void set_ambient_light(const Colorf &color);
   virtual void set_ambient_light(const Colorf &color);
   virtual void enable_light(int light_id, bool enable);
   virtual void enable_light(int light_id, bool enable);
@@ -305,7 +306,7 @@ protected:
   bool _polygon_offset_enabled;
   bool _polygon_offset_enabled;
   int _decal_level;
   int _decal_level;
 
 
-  int _cur_light_id;
+  int _max_lights;
 
 
   LMatrix4f _current_projection_mat;
   LMatrix4f _current_projection_mat;
   int _projection_mat_stack_count;
   int _projection_mat_stack_count;