From 419eadb859f937e5f0268250dde9db41cceb4df8 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 21 Jun 2015 20:28:31 +0200 Subject: [PATCH] Support hardware skinning in GLSL --- panda/src/display/standardMunger.cxx | 31 ++++--- panda/src/display/standardMunger.h | 1 + panda/src/glstuff/glGeomMunger_src.cxx | 2 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 6 +- panda/src/glstuff/glShaderContext_src.cxx | 84 +++++++++++++++++++ panda/src/glstuff/glShaderContext_src.h | 6 ++ panda/src/pgraph/shaderAttrib.h | 1 + 7 files changed, 118 insertions(+), 13 deletions(-) diff --git a/panda/src/display/standardMunger.cxx b/panda/src/display/standardMunger.cxx index 45fcc7feb1..5dc6c03d13 100644 --- a/panda/src/display/standardMunger.cxx +++ b/panda/src/display/standardMunger.cxx @@ -37,14 +37,14 @@ 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), + _shader_skinning(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 +98,9 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state, if (shader_attrib->auto_shader()) { _auto_shader = true; } + if (shader_attrib->get_flag(ShaderAttrib::F_hardware_skinning)) { + _shader_skinning = true; + } } //////////////////////////////////////////////////////////////////// @@ -128,9 +131,12 @@ munge_data_impl(const GeomVertexData *data) { } 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 (_shader_skinning) { + 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 && @@ -161,7 +167,7 @@ munge_data_impl(const GeomVertexData *data) { } } } - + CPT(GeomVertexFormat) orig_format = new_data->get_format(); CPT(GeomVertexFormat) new_format = munge_format(orig_format, animation); @@ -306,7 +312,9 @@ compare_to_impl(const GeomMunger *other) const { return compare; } } - + 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 +353,9 @@ geom_compare_to_impl(const GeomMunger *other) const { return compare; } } + if (_shader_skinning != om->_shader_skinning) { + return (int)_shader_skinning - (int)om->_shader_skinning; + } return StateMunger::geom_compare_to_impl(other); } diff --git a/panda/src/display/standardMunger.h b/panda/src/display/standardMunger.h index 872d2d8403..515a1d1ace 100644 --- a/panda/src/display/standardMunger.h +++ b/panda/src/display/standardMunger.h @@ -60,6 +60,7 @@ private: bool _munge_color; bool _munge_color_scale; bool _auto_shader; + bool _shader_skinning; LColor _color; LVecBase4 _color_scale; diff --git a/panda/src/glstuff/glGeomMunger_src.cxx b/panda/src/glstuff/glGeomMunger_src.cxx index fd98cbab1f..778fb71d95 100644 --- a/panda/src/glstuff/glGeomMunger_src.cxx +++ b/panda/src/glstuff/glGeomMunger_src.cxx @@ -158,7 +158,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()) { diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 9c6be3444c..c330776394 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -3275,11 +3275,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); @@ -3361,6 +3361,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 diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 58f78c5f6b..4c6922432f 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -211,6 +211,8 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext _uses_standard_vertex_arrays = false; _has_divisor = false; _color_attrib_index = -1; + _transform_table_index = -1; + _slider_table_index = -1; _validated = !gl_validate_shaders; nassertv(s->get_language() == Shader::SL_GLSL); @@ -883,6 +885,26 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { _shader->_mat_spec.push_back(bind); return; } + if (noprefix == "TransformTable") { + if (param_type != GL_FLOAT_MAT4) { + GLCAT.error() + << "p3d_TransformTable should be uniform mat4\n"; + return; + } + _transform_table_index = p; + _transform_table_size = param_size; + return; + } + if (noprefix == "SliderTable") { + if (param_type != GL_FLOAT) { + GLCAT.error() + << "p3d_SliderTable should be uniform float\n"; + return; + } + _slider_table_index = p; + _slider_table_size = param_size; + return; + } GLCAT.error() << "Unrecognized uniform name '" << param_name << "'!\n"; return; @@ -1586,6 +1608,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 @@ -1717,6 +1791,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; diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index 48a74f99cb..fd4b56def4 100644 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -48,6 +48,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(); @@ -74,6 +76,10 @@ private: //ParamContexts _params; GLint _color_attrib_index; + GLint _transform_table_index; + GLint _slider_table_index; + GLsizei _transform_table_size; + GLsizei _slider_table_size; pmap _glsl_uniform_handles; struct ImageInput { diff --git a/panda/src/pgraph/shaderAttrib.h b/panda/src/pgraph/shaderAttrib.h index 7bf605f9bd..d146e80bab 100644 --- a/panda/src/pgraph/shaderAttrib.h +++ b/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;