David Rose 17 年之前
父节点
当前提交
d6a9ea874d

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

@@ -1628,7 +1628,7 @@ do_issue_color_scale() {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::do_issue_light
 //     Function: GraphicsStateGuardian::do_issue_light
-//       Access: Protected
+//       Access: Protected, Virtual
 //  Description: This implementation of do_issue_light() assumes
 //  Description: This implementation of do_issue_light() assumes
 //               we have a limited number of hardware lights
 //               we have a limited number of hardware lights
 //               available.  This function assigns each light to a
 //               available.  This function assigns each light to a

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

@@ -251,7 +251,7 @@ public:
   void do_issue_clip_plane();
   void do_issue_clip_plane();
   void do_issue_color();
   void do_issue_color();
   void do_issue_color_scale();
   void do_issue_color_scale();
-  void do_issue_light();
+  virtual void do_issue_light();
 
 
   virtual void bind_light(PointLight *light_obj, const NodePath &light,
   virtual void bind_light(PointLight *light_obj, const NodePath &light,
                           int light_id);
                           int light_id);

+ 12 - 7
panda/src/glxdisplay/config_glxdisplay.cxx

@@ -33,10 +33,15 @@ ConfigureFn(config_glxdisplay) {
 }
 }
 
 
 ConfigVariableString display_cfg
 ConfigVariableString display_cfg
-("display", "");
+("display", "",
+ PRC_DESC("Specify the X display string for the default display.  If this "
+          "is not specified, $DISPLAY is used."));
 
 
-ConfigVariableBool glx_error_abort
-("glx-error-abort", false);
+ConfigVariableBool x_error_abort
+("x-error-abort", false,
+ PRC_DESC("Set this true to trigger and abort (and a stack trace) on receipt "
+          "of an error from the X window system.  This can make it easier "
+          "to discover where these errors are generated."));
 
 
 ConfigVariableBool glx_get_proc_address
 ConfigVariableBool glx_get_proc_address
 ("glx-get-proc-address", true,
 ("glx-get-proc-address", true,
@@ -52,14 +57,14 @@ ConfigVariableBool glx_get_os_address
 	  "addresses of extension functions.  This will be done only "
 	  "addresses of extension functions.  This will be done only "
 	  "if glxGetProcAddress() cannot be used for some reason."));
 	  "if glxGetProcAddress() cannot be used for some reason."));
 
 
-ConfigVariableInt glx_wheel_up_button
-("glx-wheel-up-button", 4,
+ConfigVariableInt x_wheel_up_button
+("x-wheel-up-button", 4,
  PRC_DESC("This is the mouse button index of the wheel_up event: which "
  PRC_DESC("This is the mouse button index of the wheel_up event: which "
           "mouse button number does the system report when the mouse wheel "
           "mouse button number does the system report when the mouse wheel "
           "is rolled one notch up?"));
           "is rolled one notch up?"));
 
 
-ConfigVariableInt glx_wheel_down_button
-("glx-wheel-down-button", 5,
+ConfigVariableInt x_wheel_down_button
+("x-wheel-down-button", 5,
  PRC_DESC("This is the mouse button index of the wheel_down event: which "
  PRC_DESC("This is the mouse button index of the wheel_down event: which "
           "mouse button number does the system report when the mouse wheel "
           "mouse button number does the system report when the mouse wheel "
           "is rolled one notch down?"));
           "is rolled one notch down?"));

+ 3 - 3
panda/src/glxdisplay/config_glxdisplay.h

@@ -30,11 +30,11 @@ NotifyCategoryDecl(glxdisplay, EXPCL_PANDAGL, EXPTP_PANDAGL);
 extern EXPCL_PANDAGL void init_libglxdisplay();
 extern EXPCL_PANDAGL void init_libglxdisplay();
 
 
 extern ConfigVariableString display_cfg;
 extern ConfigVariableString display_cfg;
-extern ConfigVariableBool glx_error_abort;
+extern ConfigVariableBool x_error_abort;
 extern ConfigVariableBool glx_get_proc_address;
 extern ConfigVariableBool glx_get_proc_address;
 extern ConfigVariableBool glx_get_os_address;
 extern ConfigVariableBool glx_get_os_address;
 
 
-extern ConfigVariableInt glx_wheel_up_button;
-extern ConfigVariableInt glx_wheel_down_button;
+extern ConfigVariableInt x_wheel_up_button;
+extern ConfigVariableInt x_wheel_down_button;
 
 
 #endif /* __CONFIG_GLXDISPLAY_H__ */
 #endif /* __CONFIG_GLXDISPLAY_H__ */

+ 1 - 1
panda/src/glxdisplay/glxGraphicsPipe.cxx

@@ -372,7 +372,7 @@ error_handler(Display *display, XErrorEvent *error) {
   glxdisplay_cat.error()
   glxdisplay_cat.error()
     << msg << "\n";
     << msg << "\n";
 
 
-  if (glx_error_abort) {
+  if (x_error_abort) {
     abort();
     abort();
   }
   }
 
 

+ 2 - 2
panda/src/glxdisplay/glxGraphicsWindow.cxx

@@ -1563,9 +1563,9 @@ get_button(XKeyEvent &key_event) {
 ButtonHandle glxGraphicsWindow::
 ButtonHandle glxGraphicsWindow::
 get_mouse_button(XButtonEvent &button_event) {
 get_mouse_button(XButtonEvent &button_event) {
   int index = button_event.button;
   int index = button_event.button;
-  if (index == glx_wheel_up_button) {
+  if (index == x_wheel_up_button) {
     return MouseButton::wheel_up();
     return MouseButton::wheel_up();
-  } else if (index == glx_wheel_down_button) {
+  } else if (index == x_wheel_down_button) {
     return MouseButton::wheel_down();
     return MouseButton::wheel_down();
   } else {
   } else {
     return MouseButton::button(index - 1);
     return MouseButton::button(index - 1);

+ 212 - 95
panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx

@@ -22,6 +22,10 @@
 #include "config_tinydisplay.h"
 #include "config_tinydisplay.h"
 #include "pStatTimer.h"
 #include "pStatTimer.h"
 #include "geomVertexReader.h"
 #include "geomVertexReader.h"
+#include "ambientLight.h"
+#include "pointLight.h"
+#include "directionalLight.h"
+#include "spotlight.h"
 
 
 extern "C" {
 extern "C" {
 #include "zgl.h"
 #include "zgl.h"
@@ -600,10 +604,10 @@ reset() {
 
 
   _max_texture_dimension = 256;
   _max_texture_dimension = 256;
 
 
-  // Count the max number of lights
-  GLint max_lights;
-  glGetIntegerv(GL_MAX_LIGHTS, &max_lights);
-  _max_lights = max_lights;
+  // Actually, this number is completely arbitrary, since we allocate
+  // lights dynamically.  But we probably want some limit anyway to
+  // protect users from accidentally enabling a thousand lights.
+  _max_lights = 8;
 
 
   _color_scale_via_lighting = false;
   _color_scale_via_lighting = false;
   _alpha_scale_via_texture = false;
   _alpha_scale_via_texture = false;
@@ -1424,16 +1428,6 @@ set_state_and_transform(const RenderState *target,
     _state._render_mode = _target._render_mode;
     _state._render_mode = _target._render_mode;
   }
   }
 
 
-  if ((_target._transparency != _state._transparency)||
-      (_target._color_write != _state._color_write)||
-      (_target._color_blend != _state._color_blend)) {
-    PStatTimer timer(_draw_set_state_blending_pcollector);
-    do_issue_blending();
-    _state._transparency = _target._transparency;
-    _state._color_write = _target._color_write;
-    _state._color_blend = _target._color_blend;
-  }
-
   if (_target._texture != _state._texture) {
   if (_target._texture != _state._texture) {
     PStatTimer timer(_draw_set_state_texture_pcollector);
     PStatTimer timer(_draw_set_state_texture_pcollector);
     determine_effective_texture();
     determine_effective_texture();
@@ -1529,112 +1523,235 @@ release_texture(TextureContext *tc) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: TinyGraphicsStateGuardian::enable_lighting
+//     Function: TinyGraphicsStateGuardian::do_issue_light
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
-//  Description: Intended to be overridden by a derived class to
-//               enable or disable the use of lighting overall.  This
-//               is called by do_issue_light() according to whether any
-//               lights are in use or not.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TinyGraphicsStateGuardian::
 void TinyGraphicsStateGuardian::
-enable_lighting(bool enable) {
-  static PStatCollector _draw_set_state_light_enable_lighting_pcollector("Draw:Set State:Light:Enable lighting");
-  PStatTimer timer(_draw_set_state_light_enable_lighting_pcollector);
-  
-  if (enable) {
-    glEnable(GL_LIGHTING);
-  } else {
-    glDisable(GL_LIGHTING);
+do_issue_light() {
+  // Initialize the current ambient light total and newly enabled
+  // light list
+  Colorf cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
+  int i;
+
+  int num_enabled = 0;
+  int num_on_lights = 0;
+
+  if (display_cat.is_spam()) {
+    display_cat.spam()
+      << "do_issue_light: " << _target._light << "\n";
   }
   }
+
+  // First, release all of the previously-assigned lights.
+  _c->lighting_enabled = false;
+
+  GLLight *light = _c->first_light;
+  while (light != (GLLight *)NULL) {
+    GLLight *next = light->next;
+    PANDA_FREE_SINGLE(light);
+    light = next;
+  }
+  _c->first_light = NULL;
+
+  // Now, assign new lights.
+  if (_target._light != (LightAttrib *)NULL) {
+    CPT(LightAttrib) new_light = _target._light->filter_to_max(_max_lights);
+    if (display_cat.is_spam()) {
+      new_light->write(display_cat.spam(false), 2);
+    }
+
+    num_on_lights = new_light->get_num_on_lights();
+    for (int li = 0; li < num_on_lights; li++) {
+      NodePath light = new_light->get_on_light(li);
+      nassertv(!light.is_empty());
+      Light *light_obj = light.node()->as_light();
+      nassertv(light_obj != (Light *)NULL);
+
+      _lighting_enabled = true;
+      _c->lighting_enabled = true;
+
+      if (light_obj->get_type() == AmbientLight::get_class_type()) {
+        // Accumulate all of the ambient lights together into one.
+        cur_ambient_light += light_obj->get_color();
+
+      } else {
+        // Other kinds of lights each get their own GLLight object.
+        GLLight *gl_light = (GLLight *)PANDA_MALLOC_SINGLE(sizeof(GLLight));
+        memset(gl_light, 0, sizeof(GLLight));
+        gl_light->enabled = true;
+
+        gl_light->next = _c->first_light;
+        _c->first_light = gl_light;
+
+        const Colorf &diffuse = light_obj->get_color();
+        gl_light->diffuse.X = diffuse[0];
+        gl_light->diffuse.Y = diffuse[1];
+        gl_light->diffuse.Z = diffuse[2];
+        gl_light->diffuse.W = diffuse[3];
+
+        light_obj->bind(this, light, num_enabled);
+        num_enabled++;
+      }
+    }
+  }
+
+  _c->ambient_light_model.X = cur_ambient_light[0];
+  _c->ambient_light_model.Y = cur_ambient_light[1];
+  _c->ambient_light_model.Z = cur_ambient_light[2];
+  _c->ambient_light_model.W = cur_ambient_light[3];
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: TinyGraphicsStateGuardian::set_ambient_light
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by a derived class to
-//               indicate the color of the ambient light that should
-//               be in effect.  This is called by do_issue_light() after
-//               all other lights have been enabled or disabled.
+//     Function: TinyGraphicsStateGuardian::bind_light
+//       Access: Public, Virtual
+//  Description: Called the first time a particular light has been
+//               bound to a given id within a frame, this should set
+//               up the associated hardware light with the light's
+//               properties.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TinyGraphicsStateGuardian::
 void TinyGraphicsStateGuardian::
-set_ambient_light(const Colorf &color) {
-  static PStatCollector _draw_set_state_light_ambient_pcollector("Draw:Set State:Light:Ambient");
-  PStatTimer timer(_draw_set_state_light_ambient_pcollector);
-  
-  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *)color.get_data());
+bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
+  GLLight *gl_light = _c->first_light;
+  nassertv(gl_light != (GLLight *)NULL);
+
+  const Colorf &specular = light_obj->get_specular_color();
+  gl_light->specular.X = specular[0];
+  gl_light->specular.Y = specular[1];
+  gl_light->specular.Z = specular[2];
+  gl_light->specular.W = specular[3];
+
+  // Position needs to specify x, y, z, and w
+  // w == 1 implies non-infinite position
+  CPT(TransformState) render_transform =
+    _cs_transform->compose(_scene_setup->get_world_transform());
+
+  CPT(TransformState) transform = light.get_transform(_scene_setup->get_scene_root().get_parent());
+  CPT(TransformState) net_transform = render_transform->compose(transform);
+
+  LPoint3f pos = light_obj->get_point() * net_transform->get_mat();
+  gl_light->position.X = pos[0];
+  gl_light->position.Y = pos[1];
+  gl_light->position.Z = pos[2];
+  gl_light->position.W = 1.0f;
+
+  // Exponent == 0 implies uniform light distribution
+  gl_light->spot_exponent = 0.0f;
+
+  // Cutoff == 180 means uniform point light source
+  gl_light->spot_cutoff = 180.0f;
+
+  const LVecBase3f &att = light_obj->get_attenuation();
+  gl_light->attenuation[0] = att[0];
+  gl_light->attenuation[1] = att[1];
+  gl_light->attenuation[2] = att[2];
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: TinyGraphicsStateGuardian::enable_light
-//       Access: Protected, Virtual
-//  Description: Intended to be overridden by a derived class to
-//               enable the indicated light id.  A specific Light will
-//               already have been bound to this id via bind_light().
+//     Function: TinyGraphicsStateGuardian::bind_light
+//       Access: Public, Virtual
+//  Description: Called the first time a particular light has been
+//               bound to a given id within a frame, this should set
+//               up the associated hardware light with the light's
+//               properties.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TinyGraphicsStateGuardian::
 void TinyGraphicsStateGuardian::
-enable_light(int light_id, bool enable) {
-  static PStatCollector _draw_set_state_light_enable_light_pcollector("Draw:Set State:Light:Enable light");
-  PStatTimer timer(_draw_set_state_light_enable_light_pcollector);
-  
-  if (enable) {
-    glEnable(get_light_id(light_id));
-  } else {
-    glDisable(get_light_id(light_id));
-  }
+bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
+  GLLight *gl_light = _c->first_light;
+  nassertv(gl_light != (GLLight *)NULL);
+
+  const Colorf &specular = light_obj->get_specular_color();
+  gl_light->specular.X = specular[0];
+  gl_light->specular.Y = specular[1];
+  gl_light->specular.Z = specular[2];
+  gl_light->specular.W = specular[3];
+
+  // Position needs to specify x, y, z, and w
+  // w == 0 implies light is at infinity
+  CPT(TransformState) render_transform =
+    _cs_transform->compose(_scene_setup->get_world_transform());
+
+  CPT(TransformState) transform = light.get_transform(_scene_setup->get_scene_root().get_parent());
+  CPT(TransformState) net_transform = render_transform->compose(transform);
+
+  LVector3f dir = light_obj->get_direction() * net_transform->get_mat();
+  gl_light->position.X = -dir[0];
+  gl_light->position.Y = -dir[1];
+  gl_light->position.Z = -dir[2];
+  gl_light->position.W = 0.0f;
+
+  gl_light->norm_position.X = -dir[0];
+  gl_light->norm_position.Y = -dir[1];
+  gl_light->norm_position.Z = -dir[2];
+  gl_V3_Norm(&gl_light->norm_position);
+
+  // Exponent == 0 implies uniform light distribution
+  gl_light->spot_exponent = 0.0f;
+
+  // Cutoff == 180 means uniform point light source
+  gl_light->spot_cutoff = 180.0f;
+
+  // Default attenuation values (only spotlight and point light can
+  // modify these)
+  gl_light->attenuation[0] = 1.0f;
+  gl_light->attenuation[1] = 0.0f;
+  gl_light->attenuation[2] = 0.0f;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: TinyGraphicsStateGuardian::begin_bind_lights
-//       Access: Protected, Virtual
-//  Description: Called immediately before bind_light() is called,
-//               this is intended to provide the derived class a hook
-//               in which to set up some state (like transform) that
-//               might apply to several lights.
-//
-//               The sequence is: begin_bind_lights() will be called,
-//               then one or more bind_light() calls, then
-//               end_bind_lights().
+//     Function: TinyGraphicsStateGuardian::bind_light
+//       Access: Public, Virtual
+//  Description: Called the first time a particular light has been
+//               bound to a given id within a frame, this should set
+//               up the associated hardware light with the light's
+//               properties.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TinyGraphicsStateGuardian::
 void TinyGraphicsStateGuardian::
-begin_bind_lights() {
-  static PStatCollector _draw_set_state_light_begin_bind_pcollector("Draw:Set State:Light:Begin bind");
-  PStatTimer timer(_draw_set_state_light_begin_bind_pcollector);
+bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
+  GLLight *gl_light = _c->first_light;
+  nassertv(gl_light != (GLLight *)NULL);
+
+  const Colorf &specular = light_obj->get_specular_color();
+  gl_light->specular.X = specular[0];
+  gl_light->specular.Y = specular[1];
+  gl_light->specular.Z = specular[2];
+  gl_light->specular.W = specular[3];
   
   
-  // We need to temporarily load a new matrix so we can define the
-  // light in a known coordinate system.  We pick the transform of the
-  // root.  (Alternatively, we could leave the current transform where
-  // it is and compute the light position relative to that transform
-  // instead of relative to the root, by composing with the matrix
-  // computed by _internal_transform->invert_compose(render_transform).
-  // But I think loading a completely new matrix is simpler.)
+  Lens *lens = light_obj->get_lens();
+  nassertv(lens != (Lens *)NULL);
+
+  // Position needs to specify x, y, z, and w
+  // w == 1 implies non-infinite position
   CPT(TransformState) render_transform =
   CPT(TransformState) render_transform =
     _cs_transform->compose(_scene_setup->get_world_transform());
     _cs_transform->compose(_scene_setup->get_world_transform());
 
 
-  /*
-  glMatrixMode(GL_MODELVIEW);
-  glPushMatrix();
-  glLoadMatrixf(render_transform->get_mat().get_data());
-  */
-}
+  CPT(TransformState) transform = light.get_transform(_scene_setup->get_scene_root().get_parent());
+  CPT(TransformState) net_transform = render_transform->compose(transform);
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: TinyGraphicsStateGuardian::end_bind_lights
-//       Access: Protected, Virtual
-//  Description: Called after before bind_light() has been called one
-//               or more times (but before any geometry is issued or
-//               additional state is changed), this is intended to
-//               clean up any temporary changes to the state that may
-//               have been made by begin_bind_lights().
-////////////////////////////////////////////////////////////////////
-void TinyGraphicsStateGuardian::
-end_bind_lights() {
-  static PStatCollector _draw_set_state_light_end_bind_pcollector("Draw:Set State:Light:End bind");
-  PStatTimer timer(_draw_set_state_light_end_bind_pcollector);
+  const LMatrix4f &light_mat = net_transform->get_mat();
+  LPoint3f pos = lens->get_nodal_point() * light_mat;
+  LVector3f dir = lens->get_view_vector() * light_mat;
 
 
-  /*
-  glMatrixMode(GL_MODELVIEW);
-  glPopMatrix();
-  */
+  gl_light->position.X = pos[0];
+  gl_light->position.Y = pos[1];
+  gl_light->position.Z = pos[2];
+  gl_light->position.W = 1.0f;
+
+  gl_light->spot_direction.X = dir[0];
+  gl_light->spot_direction.Y = dir[1];
+  gl_light->spot_direction.Z = dir[2];
+
+  gl_light->norm_spot_direction.X = dir[0];
+  gl_light->norm_spot_direction.Y = dir[1];
+  gl_light->norm_spot_direction.Z = dir[2];
+  gl_V3_Norm(&gl_light->norm_spot_direction);
+
+  gl_light->spot_exponent = light_obj->get_exponent();
+  gl_light->spot_cutoff = lens->get_hfov() * 0.5f;
+
+  const LVecBase3f &att = light_obj->get_attenuation();
+  gl_light->attenuation[0] = att[0];
+  gl_light->attenuation[1] = att[1];
+  gl_light->attenuation[2] = att[2];
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 7 - 5
panda/src/tinydisplay/tinyGraphicsStateGuardian.h

@@ -90,11 +90,13 @@ public:
   virtual TextureContext *prepare_texture(Texture *tex);
   virtual TextureContext *prepare_texture(Texture *tex);
   virtual void release_texture(TextureContext *tc);
   virtual void release_texture(TextureContext *tc);
 
 
-  virtual void enable_lighting(bool enable);
-  virtual void set_ambient_light(const Colorf &color);
-  virtual void enable_light(int light_id, bool enable);
-  virtual void begin_bind_lights();
-  virtual void end_bind_lights();
+  virtual void do_issue_light();
+  virtual void bind_light(PointLight *light_obj, const NodePath &light,
+                          int light_id);
+  virtual void bind_light(DirectionalLight *light_obj, const NodePath &light,
+                          int light_id);
+  virtual void bind_light(Spotlight *light_obj, const NodePath &light,
+                          int light_id);
 
 
 private:
 private:
   void do_issue_transform();
   void do_issue_transform();