Browse Source

Add F_hardware_skinning/p3d_TransformTable to GLSL on 1.9 branch, as requested
Uses a hack to prevent breaking ABI compat

rdb 10 years ago
parent
commit
e1c0ae7f1b

+ 28 - 12
panda/src/display/standardMunger.cxx

@@ -37,14 +37,13 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
   StateMunger(gsg),
   _num_components(num_components),
   _numeric_type(numeric_type),
-  _contents(contents)
+  _contents(contents),
+  _munge_color(false),
+  _munge_color_scale(false),
+  _auto_shader(false)
 {
   _render_mode = DCAST(RenderModeAttrib, state->get_attrib(RenderModeAttrib::get_class_slot()));
 
-  _munge_color = false;
-  _munge_color_scale = false;
-  _auto_shader = false;
-
   if (!get_gsg()->get_runtime_color_scale()) {
     // We might need to munge the colors.
     const ColorAttrib *color_attrib = (const ColorAttrib *)
@@ -98,6 +97,11 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
   if (shader_attrib->auto_shader()) {
     _auto_shader = true;
   }
+  if (shader_attrib->get_flag(ShaderAttrib::F_hardware_skinning)) {
+    // Hijack this field, such as not to break ABI compatibility.
+    // This hack is not present in 1.10.
+    _num_components |= 0x10000;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -120,17 +124,20 @@ munge_data_impl(const GeomVertexData *data) {
   CPT(GeomVertexData) new_data = data;
 
   if (_munge_color) {
-    new_data = new_data->set_color(_color, _num_components, _numeric_type,
-                                   _contents);
+    new_data = new_data->set_color(_color, _num_components & 0xffff,
+                                   _numeric_type, _contents);
   } else if (_munge_color_scale) {
-    new_data = new_data->scale_color(_color_scale, _num_components, 
+    new_data = new_data->scale_color(_color_scale, _num_components & 0xffff,
                                      _numeric_type, _contents);
   }
 
   GeomVertexAnimationSpec animation = new_data->get_format()->get_animation();
-  if (hardware_animated_vertices &&
-      animation.get_animation_type() == AT_panda &&
-      new_data->get_slider_table() == (SliderTable *)NULL) {
+  if (_num_components & 0x10000) {
+    animation.set_hardware(4, true);
+
+  } else if (hardware_animated_vertices &&
+             animation.get_animation_type() == AT_panda &&
+             new_data->get_slider_table() == (SliderTable *)NULL) {
     // Maybe we can animate the vertices with hardware.
     const TransformBlendTable *table = new_data->get_transform_blend_table();
     if (table != (TransformBlendTable *)NULL &&
@@ -306,7 +313,11 @@ compare_to_impl(const GeomMunger *other) const {
       return compare;
     }
   }
-
+  bool shader_skinning = ((_num_components & 0x10000) != 0);
+  bool om_shader_skinning = ((om->_num_components & 0x10000) != 0);
+  if (shader_skinning != om_shader_skinning) {
+    return (int)shader_skinning - (int)om_shader_skinning;
+  }
   if (_auto_shader != om->_auto_shader) {
     return (int)_auto_shader - (int)om->_auto_shader;
   }
@@ -345,6 +356,11 @@ geom_compare_to_impl(const GeomMunger *other) const {
       return compare;
     }
   }
+  bool shader_skinning = ((_num_components & 0x10000) != 0);
+  bool om_shader_skinning = ((om->_num_components & 0x10000) != 0);
+  if (shader_skinning != om_shader_skinning) {
+    return (int)shader_skinning - (int)om_shader_skinning;
+  }
 
   return StateMunger::geom_compare_to_impl(other);
 }

+ 1 - 1
panda/src/glstuff/glGeomMunger_src.cxx

@@ -118,7 +118,7 @@ munge_format_impl(const GeomVertexFormat *orig,
     if (animation.get_num_transforms() > 1) {
       PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
       new_array_format->add_column
-        (InternalName::get_transform_weight(), animation.get_num_transforms() - 1,
+        (InternalName::get_transform_weight(), animation.get_num_transforms(),
          NT_stdfloat, C_other);
 
       if (animation.get_indexed_transforms()) {

+ 4 - 2
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -3249,11 +3249,11 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
     }
   }
 
+#ifndef OPENGLES
   const GeomVertexAnimationSpec &animation =
     _data_reader->get_format()->get_animation();
   bool hardware_animation = (animation.get_animation_type() == Geom::AT_hardware);
-#ifndef OPENGLES
-  if (hardware_animation) {
+  if (hardware_animation && _current_shader_context == NULL) {
     // Set up the transform matrices for vertex blending.
     nassertr(_supports_vertex_blend, false);
     glEnable(GL_VERTEX_BLEND_ARB);
@@ -3335,6 +3335,8 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
       GLPf(LoadMatrix)(_internal_transform->get_mat().get_data());
     }
   }
+#else
+  const bool hardware_animation = false;
 #endif
 
 #ifndef OPENGLES_2

+ 84 - 0
panda/src/glstuff/glShaderContext_src.cxx

@@ -197,6 +197,8 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
   _glsl_program = 0;
   _uses_standard_vertex_arrays = false;
   _has_divisor = false;
+  _transform_table_index = -1;
+  _slider_table_index = -1;
 
   nassertv(s->get_language() == Shader::SL_GLSL);
 
@@ -527,6 +529,26 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
             s->_mat_spec.push_back(bind);
             continue;
           }
+          if (noprefix == "TransformTable") {
+            if (param_type != GL_FLOAT_MAT4) {
+              GLCAT.error()
+                << "p3d_TransformTable should be uniform mat4\n";
+              continue;
+            }
+            _transform_table_index = p;
+            _transform_table_size = param_size;
+            continue;
+          }
+          if (noprefix == "SliderTable") {
+            if (param_type != GL_FLOAT) {
+              GLCAT.error()
+                << "p3d_SliderTable should be uniform float\n";
+              continue;
+            }
+            _slider_table_index = p;
+            _slider_table_size = param_size;
+            continue;
+          }
           GLCAT.error() << "Unrecognized uniform name '" << param_name_cstr << "'!\n";
           continue;
 
@@ -1324,6 +1346,58 @@ issue_parameters(int altered) {
   _glgsg->report_my_gl_errors();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLShaderContext::update_transform_table
+//       Access: Public
+//  Description: Changes the active transform table, used for hardware
+//               skinning.
+////////////////////////////////////////////////////////////////////
+void CLP(ShaderContext)::
+update_transform_table(const TransformTable *table) {
+  LMatrix4f *matrices = (LMatrix4f *)alloca(_transform_table_size * 64);
+
+  int i = 0;
+  if (table != NULL) {
+    int num_transforms = min(_transform_table_size, table->get_num_transforms());
+    for (; i < num_transforms; ++i) {
+#ifdef STDFLOAT_DOUBLE
+      LMatrix4 matrix;
+      table->get_transform(i)->get_matrix(matrix);
+      matrices[i] = LCAST(float, matrix);
+#else
+      table->get_transform(i)->get_matrix(matrices[i]);
+#endif
+    }
+  }
+  for (; i < _transform_table_size; ++i) {
+    matrices[i] = LMatrix4f::ident_mat();
+  }
+
+  _glgsg->_glUniformMatrix4fv(_transform_table_index, _transform_table_size,
+                              GL_FALSE, (float *)matrices);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLShaderContext::update_slider_table
+//       Access: Public
+//  Description: Changes the active slider table, used for hardware
+//               skinning.
+////////////////////////////////////////////////////////////////////
+void CLP(ShaderContext)::
+update_slider_table(const SliderTable *table) {
+  float *sliders = (float *)alloca(_slider_table_size * 4);
+  memset(sliders, 0, _slider_table_size * 4);
+
+  if (table != NULL) {
+    int num_sliders = min(_slider_table_size, table->get_num_sliders());
+    for (int i = 0; i < num_sliders; ++i) {
+      sliders[i] = table->get_slider(i)->get_slider();
+    }
+  }
+
+  _glgsg->_glUniform1fv(_slider_table_index, _slider_table_size, sliders);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GLShaderContext::disable_shader_vertex_arrays
 //       Access: Public
@@ -1441,6 +1515,16 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
     }
   }
 
+  if (_transform_table_index >= 0) {
+    const TransformTable *table = _glgsg->_data_reader->get_transform_table();
+    update_transform_table(table);
+  }
+
+  if (_slider_table_index >= 0) {
+    const SliderTable *table = _glgsg->_data_reader->get_slider_table();
+    update_slider_table(table);
+  }
+
   _glgsg->report_my_gl_errors();
 
   return true;

+ 7 - 0
panda/src/glstuff/glShaderContext_src.h

@@ -41,6 +41,8 @@ public:
   void bind(bool reissue_parameters = true);
   void unbind();
   void issue_parameters(int altered);
+  void update_transform_table(const TransformTable *table);
+  void update_slider_table(const SliderTable *table);
   void disable_shader_vertex_arrays();
   bool update_shader_vertex_arrays(ShaderContext *prev, bool force);
   void disable_shader_texture_bindings();
@@ -65,6 +67,11 @@ private:
   //typedef pvector<ParamContext> ParamContexts;
   //ParamContexts _params;
 
+  GLint _transform_table_index;
+  GLint _slider_table_index;
+  GLsizei _transform_table_size;
+  GLsizei _slider_table_size;
+
   pvector<GLint> _glsl_parameter_map;
   pmap<GLint, GLuint64> _glsl_uniform_handles;
 

+ 1 - 0
panda/src/pgraph/shaderAttrib.h

@@ -48,6 +48,7 @@ PUBLISHED:
   enum {
     F_disable_alpha_write = 0,  // Suppress writes to color buffer alpha channel.
     F_subsume_alpha_test  = 1,  // Shader promises to subsume the alpha test using TEXKILL
+    F_hardware_skinning   = 2,  // Shader needs pre-animated vertices
   };
 
   INLINE bool               has_shader() const;