Add F_hardware_skinning/p3d_TransformTable to GLSL on 1.9 branch, as requested

Uses a hack to prevent breaking ABI compat
This commit is contained in:
rdb 2015-09-05 15:28:12 +02:00
parent c33f3b3dca
commit e1c0ae7f1b
6 changed files with 125 additions and 15 deletions

View File

@ -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);
}

View File

@ -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()) {

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;