From e1c0ae7f1be9e8478778306a0d42acc89a97bfb8 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 5 Sep 2015 15:28:12 +0200 Subject: [PATCH] Add F_hardware_skinning/p3d_TransformTable to GLSL on 1.9 branch, as requested Uses a hack to prevent breaking ABI compat --- panda/src/display/standardMunger.cxx | 40 ++++++--- 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 | 7 ++ panda/src/pgraph/shaderAttrib.h | 1 + 6 files changed, 125 insertions(+), 15 deletions(-) diff --git a/panda/src/display/standardMunger.cxx b/panda/src/display/standardMunger.cxx index 922150a114..c33c95f7e2 100644 --- a/panda/src/display/standardMunger.cxx +++ b/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); } diff --git a/panda/src/glstuff/glGeomMunger_src.cxx b/panda/src/glstuff/glGeomMunger_src.cxx index b2deb6e29f..a3b53ac464 100644 --- a/panda/src/glstuff/glGeomMunger_src.cxx +++ b/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()) { diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index a1a2e7e7a9..2d0c82e0b9 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/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 diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 5df6c93871..298eda1f9e 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/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; diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index e2a9aadc9d..62d54ed675 100644 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/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 ParamContexts; //ParamContexts _params; + GLint _transform_table_index; + GLint _slider_table_index; + GLsizei _transform_table_size; + GLsizei _slider_table_size; + pvector _glsl_parameter_map; pmap _glsl_uniform_handles; diff --git a/panda/src/pgraph/shaderAttrib.h b/panda/src/pgraph/shaderAttrib.h index c6bb2eb583..9d677a411e 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;