diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index fb630022d4..5e67cb81e7 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -996,6 +996,16 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 & 0.0); return &t; } + case Shader::SMO_frame_time: { + PN_stdfloat time = ClockObject::get_global_clock()->get_frame_time(); + t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, time, time, time, time); + return &t; + } + case Shader::SMO_frame_delta: { + PN_stdfloat dt = ClockObject::get_global_clock()->get_dt(); + t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dt, dt, dt, dt); + return &t; + } case Shader::SMO_texpad_x: { Texture *tex = _target_shader->get_shader_input_texture(name); nassertr(tex != 0, &LMatrix4::zeros_mat()); diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 281ab0cef9..5bd6d9d7d0 100755 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -71,14 +71,13 @@ TypeHandle CLP(ShaderContext)::_type_handle; bool CLP(ShaderContext):: parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objShader) { Shader::ShaderArgInfo p; - p._id = arg_id; - + string basename(arg_id._name); // Split it at the underscores. vector_string pieces; tokenize(basename, pieces, "_"); - + if (pieces[0] == "mstrans") { pieces[0] = "trans"; pieces.push_back("to"); @@ -119,9 +118,9 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objSha pieces.push_back("to"); pieces.push_back("clip"); } - - if ((pieces[0] == "mat")||(pieces[0] == "inv")|| - (pieces[0] == "tps")||(pieces[0] == "itp")) { + + if ((pieces[0] == "mat") || (pieces[0] == "inv") || + (pieces[0] == "tps") || (pieces[0] == "itp")) { if (!objShader->cp_errchk_parameter_words(p, 2)) { return false; } @@ -138,33 +137,33 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objSha objShader->cp_report_error(p,"unrecognized matrix name"); return false; } - if (trans=="mat") { + if (trans == "mat") { pieces[0] = "trans"; - } else if (trans=="inv") { + } else if (trans == "inv") { string t = pieces[1]; pieces[1] = pieces[3]; pieces[3] = t; - } else if (trans=="tps") { + } else if (trans == "tps") { pieces[0] = "tpose"; - } else if (trans=="itp") { + } else if (trans == "itp") { string t = pieces[1]; pieces[1] = pieces[3]; pieces[3] = t; pieces[0] = "tpose"; - } + } } // Implement the transform-matrix generator. - if ((pieces[0]=="trans")|| - (pieces[0]=="tpose")|| - (pieces[0]=="row0")|| - (pieces[0]=="row1")|| - (pieces[0]=="row2")|| - (pieces[0]=="row3")|| - (pieces[0]=="col0")|| - (pieces[0]=="col1")|| - (pieces[0]=="col2")|| - (pieces[0]=="col3")) { + if ((pieces[0] == "trans") || + (pieces[0] == "tpose") || + (pieces[0] == "row0") || + (pieces[0] == "row1") || + (pieces[0] == "row2") || + (pieces[0] == "row3") || + (pieces[0] == "col0") || + (pieces[0] == "col1") || + (pieces[0] == "col2") || + (pieces[0] == "col3")) { Shader::ShaderMatSpec bind; bind._id = arg_id; @@ -174,27 +173,26 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objSha pieces.push_back(""); // Decide whether this is a matrix or vector. - if (pieces[0]=="trans") bind._piece = Shader::SMP_whole; - else if (pieces[0]=="tpose") bind._piece = Shader::SMP_transpose; - else if (pieces[0]=="row0") bind._piece = Shader::SMP_row0; - else if (pieces[0]=="row1") bind._piece = Shader::SMP_row1; - else if (pieces[0]=="row2") bind._piece = Shader::SMP_row2; - else if (pieces[0]=="row3") bind._piece = Shader::SMP_row3; - else if (pieces[0]=="col0") bind._piece = Shader::SMP_col0; - else if (pieces[0]=="col1") bind._piece = Shader::SMP_col1; - else if (pieces[0]=="col2") bind._piece = Shader::SMP_col2; - else if (pieces[0]=="col3") bind._piece = Shader::SMP_col3; + if (pieces[0] == "trans") bind._piece = Shader::SMP_whole; + else if (pieces[0] == "tpose") bind._piece = Shader::SMP_transpose; + else if (pieces[0] == "row0") bind._piece = Shader::SMP_row0; + else if (pieces[0] == "row1") bind._piece = Shader::SMP_row1; + else if (pieces[0] == "row2") bind._piece = Shader::SMP_row2; + else if (pieces[0] == "row3") bind._piece = Shader::SMP_row3; + else if (pieces[0] == "col0") bind._piece = Shader::SMP_col0; + else if (pieces[0] == "col1") bind._piece = Shader::SMP_col1; + else if (pieces[0] == "col2") bind._piece = Shader::SMP_col2; + else if (pieces[0] == "col3") bind._piece = Shader::SMP_col3; if (!objShader->cp_parse_coord_sys(p, pieces, next, bind, true)) { return false; } if (!objShader->cp_parse_delimiter(p, pieces, next)) { return false; - } + } if (!objShader->cp_parse_coord_sys(p, pieces, next, bind, false)) { return false; } - if (!objShader->cp_parse_eol(p, pieces, next)) { return false; } @@ -338,7 +336,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { } bind._arg[0] = NULL; bind._arg[1] = NULL; - + if (matrix_name == "ModelViewProjectionMatrix") { bind._func = Shader::SMF_compose; if (inverse) { @@ -418,15 +416,14 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { // them as well, to increase compatibility. // Other inputs we may support in the future: // int osg_FrameNumber - // float osg_FrameTime - // float osg_DeltaFrameTime + + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._arg[0] = NULL; + bind._arg[1] = NULL; if (param_name == "osg_ViewMatrix") { - Shader::ShaderMatSpec bind; - bind._id = arg_id; bind._piece = Shader::SMP_whole; - bind._arg[0] = NULL; - bind._arg[1] = NULL; bind._func = Shader::SMF_first; bind._part[0] = Shader::SMO_world_to_view; bind._part[1] = Shader::SMO_identity; @@ -436,11 +433,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { continue; } else if (param_name == "osg_InverseViewMatrix") { - Shader::ShaderMatSpec bind; - bind._id = arg_id; bind._piece = Shader::SMP_whole; - bind._arg[0] = NULL; - bind._arg[1] = NULL; bind._func = Shader::SMF_first; bind._part[0] = Shader::SMO_view_to_world; bind._part[1] = Shader::SMO_identity; @@ -448,6 +441,26 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { bind._dep[1] = Shader::SSD_NONE; s->_mat_spec.push_back(bind); continue; + + } else if (param_name == "osg_FrameTime") { + bind._piece = Shader::SMP_row3x1; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_frame_time; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; + + } else if (param_name == "osg_DeltaFrameTime") { + bind._piece = Shader::SMP_row3x1; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_frame_delta; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; } } @@ -455,7 +468,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { if (parse_and_set_short_hand_shader_vars(arg_id, s)) { continue; } - + if (param_size == 1) { switch (param_type) { #ifndef OPENGLES @@ -706,7 +719,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { } } } - + gsg->report_my_gl_errors(); } @@ -1162,12 +1175,13 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, } } #endif - + InternalName *name = _shader->_var_spec[i]._name; int texslot = _shader->_var_spec[i]._append_uv; if (texslot >= 0 && texslot < gsg->_state_texture->get_num_on_stages()) { TextureStage *stage = gsg->_state_texture->get_on_stage(texslot); InternalName *texname = stage->get_texcoord_name(); + if (name == InternalName::get_texcoord()) { name = texname; } else if (texname != InternalName::get_texcoord()) { diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 8807206409..675fbca876 100755 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -414,23 +414,23 @@ cp_dependency(ShaderMatInput inp) { (inp == SMO_view_to_model)) { dep |= SSD_transform; } - if ((inp == SMO_texpad_x)|| - (inp == SMO_texpix_x)|| - (inp == SMO_alight_x)|| - (inp == SMO_dlight_x)|| - (inp == SMO_plight_x)|| - (inp == SMO_slight_x)|| - (inp == SMO_satten_x)|| - (inp == SMO_mat_constant_x)|| - (inp == SMO_vec_constant_x)|| - (inp == SMO_clipplane_x)|| - (inp == SMO_view_x_to_view)|| - (inp == SMO_view_to_view_x)|| - (inp == SMO_apiview_x_to_view)|| - (inp == SMO_view_to_apiview_x)|| - (inp == SMO_clip_x_to_view)|| - (inp == SMO_view_to_clip_x)|| - (inp == SMO_apiclip_x_to_view)|| + if ((inp == SMO_texpad_x) || + (inp == SMO_texpix_x) || + (inp == SMO_alight_x) || + (inp == SMO_dlight_x) || + (inp == SMO_plight_x) || + (inp == SMO_slight_x) || + (inp == SMO_satten_x) || + (inp == SMO_mat_constant_x) || + (inp == SMO_vec_constant_x) || + (inp == SMO_clipplane_x) || + (inp == SMO_view_x_to_view) || + (inp == SMO_view_to_view_x) || + (inp == SMO_apiview_x_to_view) || + (inp == SMO_view_to_apiview_x) || + (inp == SMO_clip_x_to_view) || + (inp == SMO_view_to_clip_x) || + (inp == SMO_apiclip_x_to_view) || (inp == SMO_view_to_apiclip_x)) { dep |= SSD_shaderinputs; } @@ -588,36 +588,45 @@ compile_parameter(const ShaderArgId &arg_id, } ShaderVarSpec bind; bind._id = arg_id; + bind._append_uv = -1; + if (pieces.size() == 2) { - if (pieces[1]=="position") { + if (pieces[1] == "position") { bind._name = InternalName::get_vertex(); bind._append_uv = -1; _var_spec.push_back(bind); return true; } - if (pieces[1].substr(0,8)=="texcoord") { + if (pieces[1].substr(0, 8) == "texcoord") { bind._name = InternalName::get_texcoord(); - bind._append_uv = atoi(pieces[1].c_str()+8); + if (pieces[1].size() > 8) { + bind._append_uv = atoi(pieces[1].c_str() + 8); + } _var_spec.push_back(bind); return true; } - if (pieces[1].substr(0,7)=="tangent") { + if (pieces[1].substr(0, 7) == "tangent") { bind._name = InternalName::get_tangent(); - bind._append_uv = atoi(pieces[1].c_str()+7); + if (pieces[1].size() > 7) { + bind._append_uv = atoi(pieces[1].c_str() + 7); + } _var_spec.push_back(bind); return true; } - if (pieces[1].substr(0,8)=="binormal") { + if (pieces[1].substr(0, 8) == "binormal") { bind._name = InternalName::get_binormal(); - bind._append_uv = atoi(pieces[1].c_str()+8); + if (pieces[1].size() > 8) { + bind._append_uv = atoi(pieces[1].c_str() + 8); + } _var_spec.push_back(bind); return true; } } + bind._name = InternalName::get_root(); - bind._append_uv = -1; - for (int i=1; i<(int)(pieces.size()-0); i++) + for (int i = 1; i < pieces.size(); ++i) { bind._name = bind._name->append(pieces[i]); + } _var_spec.push_back(bind); return true; } @@ -1008,7 +1017,7 @@ compile_parameter(const ShaderArgId &arg_id, // Keywords to access unusual parameters. if (pieces[0] == "sys") { - if ((!cp_errchk_parameter_words(p,2)) || + if ((!cp_errchk_parameter_words(p, 2)) || (!cp_errchk_parameter_in(p)) || (!cp_errchk_parameter_uniform(p))) { return false; @@ -1025,14 +1034,24 @@ compile_parameter(const ShaderArgId &arg_id, } bind._part[0] = SMO_pixel_size; bind._arg[0] = NULL; + } else if (pieces[1] == "windowsize") { if (!cp_errchk_parameter_float(p, 2, 2)) { return false; } bind._part[0] = SMO_window_size; bind._arg[0] = NULL; + + } else if (pieces[1] == "time") { + if (!cp_errchk_parameter_float(p, 1, 1)) { + return false; + } + bind._piece = SMP_row3x1; + bind._part[0] = SMO_frame_time; + bind._arg[0] = NULL; + } else { - cp_report_error(p,"unknown system parameter"); + cp_report_error(p, "unknown system parameter"); return false; } diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index 420fc0ab8f..7980a3dc78 100755 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -30,7 +30,7 @@ #include "pta_LVecBase2.h" #ifdef HAVE_CG -// I don't want to include the Cg header file into panda as a +// I don't want to include the Cg header file into panda as a // whole. Instead, I'll just excerpt some opaque declarations. typedef struct _CGcontext *CGcontext; typedef struct _CGprogram *CGprogram; @@ -40,8 +40,8 @@ typedef struct _CGparameter *CGparameter; //////////////////////////////////////////////////////////////////// // Class : Shader // Summary: The Shader class is meant to select the Shader Language, -// select the available profile, compile the shader, and -// finally compile and store the shader parameters +// select the available profile, compile the shader, and +// finally compile and store the shader parameters // in the appropriate structure. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_GOBJ Shader : public TypedWritableReferenceCount { @@ -115,11 +115,11 @@ public: SMO_pixel_size, SMO_texpad_x, SMO_texpix_x, - + SMO_attr_material, SMO_attr_color, SMO_attr_colorscale, - + SMO_alight_x, SMO_dlight_x, SMO_plight_x, @@ -128,7 +128,7 @@ public: SMO_texmat_x, SMO_plane_x, SMO_clipplane_x, - + SMO_mat_constant_x, SMO_vec_constant_x, @@ -146,7 +146,7 @@ public: SMO_apiclip_to_view, SMO_view_to_apiclip, - + SMO_view_x_to_view, SMO_view_to_view_x, @@ -161,11 +161,15 @@ public: SMO_attr_fog, SMO_attr_fogcolor, - + + SMO_frame_number, + SMO_frame_time, + SMO_frame_delta, + SMO_INVALID }; - - enum ShaderArgClass { + + enum ShaderArgClass { SAC_scalar, SAC_vector, SAC_matrix, @@ -173,28 +177,28 @@ public: SAC_array, SAC_unknown, }; - - enum ShaderArgType { - SAT_scalar, - SAT_vec1, - SAT_vec2, - SAT_vec3, - SAT_vec4, - SAT_mat1x1, - SAT_mat1x2, - SAT_mat1x3, + + enum ShaderArgType { + SAT_scalar, + SAT_vec1, + SAT_vec2, + SAT_vec3, + SAT_vec4, + SAT_mat1x1, + SAT_mat1x2, + SAT_mat1x3, SAT_mat1x4, SAT_mat2x1, - SAT_mat2x2, - SAT_mat2x3, - SAT_mat2x4, - SAT_mat3x1, - SAT_mat3x2, - SAT_mat3x3, - SAT_mat3x4, - SAT_mat4x1, - SAT_mat4x2, - SAT_mat4x3, + SAT_mat2x2, + SAT_mat2x3, + SAT_mat2x4, + SAT_mat3x1, + SAT_mat3x2, + SAT_mat3x3, + SAT_mat3x4, + SAT_mat4x1, + SAT_mat4x2, + SAT_mat4x3, SAT_mat4x4, SAT_sampler1d, SAT_sampler2d, @@ -230,20 +234,20 @@ public: }; enum ShaderStateDep { - SSD_NONE = 0, - SSD_general = 1, - SSD_transform = 2, - SSD_color = 4, - SSD_colorscale = 8, - SSD_material = 16, - SSD_shaderinputs = 32, - SSD_fog = 64, + SSD_NONE = 0x000, + SSD_general = 0x001, + SSD_transform = 0x002, + SSD_color = 0x004, + SSD_colorscale = 0x008, + SSD_material = 0x010, + SSD_shaderinputs = 0x020, + SSD_fog = 0x040, }; enum ShaderBug { SBUG_ati_draw_buffers, }; - + enum ShaderMatFunc { SMF_compose, SMF_transform_dlight, @@ -251,36 +255,36 @@ public: SMF_transform_slight, SMF_first, }; - + struct ShaderArgId { string _name; ShaderType _type; int _seqno; - }; - - struct ShaderArgInfo { + }; + + struct ShaderArgInfo { ShaderArgId _id; ShaderArgClass _class; ShaderArgClass _subclass; - ShaderArgType _type; + ShaderArgType _type; ShaderArgDir _direction; bool _varying; NotifyCategory *_cat; }; - + enum ShaderPtrType { SPT_float, SPT_double, SPT_unknown - }; - + }; + // Container structure for data of parameters ShaderPtrSpec. struct ShaderPtrData { private: PT(ReferenceCount) _pta; public: - void *_ptr; + void *_ptr; ShaderPtrType _type; bool _updated; int _size; //number of elements vec3[4]=12 @@ -339,8 +343,8 @@ public: PT(InternalName) _name; int _append_uv; }; - - struct ShaderPtrSpec { + + struct ShaderPtrSpec { ShaderArgId _id; int _dim[3]; //n_elements,rows,cols int _dep[2]; @@ -376,8 +380,8 @@ public: public: INLINE ShaderFile() {}; INLINE ShaderFile(const string &shared); - INLINE ShaderFile(const string &vertex, - const string &fragment, + INLINE ShaderFile(const string &vertex, + const string &fragment, const string &geometry, const string &tess_control, const string &tess_evaluation); @@ -404,18 +408,18 @@ public: void parse_upto(string &result, string pattern, bool include); void parse_rest(string &result); bool parse_eof(); - + void cp_report_error(ShaderArgInfo &arg, const string &msg); bool cp_errchk_parameter_words(ShaderArgInfo &arg, int len); bool cp_errchk_parameter_in(ShaderArgInfo &arg); - bool cp_errchk_parameter_ptr(ShaderArgInfo &p); + bool cp_errchk_parameter_ptr(ShaderArgInfo &p); bool cp_errchk_parameter_varying(ShaderArgInfo &arg); bool cp_errchk_parameter_uniform(ShaderArgInfo &arg); bool cp_errchk_parameter_float(ShaderArgInfo &arg, int lo, int hi); bool cp_errchk_parameter_sampler(ShaderArgInfo &arg); bool cp_parse_eol(ShaderArgInfo &arg, vector_string &pieces, int &next); - bool cp_parse_delimiter(ShaderArgInfo &arg, + bool cp_parse_delimiter(ShaderArgInfo &arg, vector_string &pieces, int &next); string cp_parse_non_delimiter(vector_string &pieces, int &next); bool cp_parse_coord_sys(ShaderArgInfo &arg, @@ -425,12 +429,12 @@ public: void cp_optimize_mat_spec(ShaderMatSpec &spec); #ifdef HAVE_CG - void cg_recurse_parameters(CGparameter parameter, - const ShaderType &type, + void cg_recurse_parameters(CGparameter parameter, + const ShaderType &type, bool &success); #endif - - bool compile_parameter(const ShaderArgId &arg_id, + + bool compile_parameter(const ShaderArgId &arg_id, const ShaderArgClass &arg_class, const ShaderArgClass &arg_subclass, const ShaderArgType &arg_type, @@ -443,7 +447,7 @@ public: #ifdef HAVE_CG private: - ShaderArgClass cg_parameter_class(CGparameter p); + ShaderArgClass cg_parameter_class(CGparameter p); ShaderArgType cg_parameter_type(CGparameter p); ShaderArgDir cg_parameter_dir(CGparameter p); @@ -455,7 +459,7 @@ private: bool cg_compile_shader(const ShaderCaps &caps); void cg_release_resources(); void cg_report_errors(); - + // Determines the appropriate cg profile settings and stores them in the active shader caps // based on any profile settings stored in the shader's header void cg_get_profile_from_header(ShaderCaps &caps); @@ -477,24 +481,24 @@ public: bool cg_compile_for(const ShaderCaps &caps, CGcontext &ctx, CGprogram &vprogram, CGprogram &fprogram, CGprogram &gprogram, pvector &map); - + #endif public: - pvector _ptr_spec; + pvector _ptr_spec; epvector _mat_spec; pvector _tex_spec; pvector _var_spec; - + bool _error_flag; CPT(ShaderFile) _text; protected: - CPT(ShaderFile) _filename; + CPT(ShaderFile) _filename; int _parse; bool _loaded; ShaderLanguage _language; - + static ShaderCaps _default_caps; static ShaderUtilization _shader_utilization; static int _shaders_generated; @@ -510,7 +514,7 @@ protected: typedef pmap Contexts; Contexts _contexts; -private: +private: void clear_prepared(PreparedGraphicsObjects *prepared_objects); Shader(); diff --git a/panda/src/pgraphnodes/shaderGenerator.cxx b/panda/src/pgraphnodes/shaderGenerator.cxx index b77dddd5c4..7460a102ff 100644 --- a/panda/src/pgraphnodes/shaderGenerator.cxx +++ b/panda/src/pgraphnodes/shaderGenerator.cxx @@ -622,15 +622,13 @@ synthesize_shader(const RenderState *rs) { // These variables will hold the results of register allocation. - char *ntangent_vreg = 0; - char *ntangent_freg = 0; - char *nbinormal_vreg = 0; - char *nbinormal_freg = 0; - char *htangent_vreg = 0; - char *hbinormal_vreg = 0; - pvector texcoord_freg; - pvector dlightcoord_freg; - pvector slightcoord_freg; + char *tangent_freg = 0; + char *binormal_freg = 0; + string tangent_input; + string binormal_input; + pmap texcoord_fregs; + pvector dlightcoord_fregs; + pvector slightcoord_fregs; char *world_position_freg = 0; char *world_normal_freg = 0; char *eye_position_freg = 0; @@ -659,11 +657,39 @@ synthesize_shader(const RenderState *rs) { for (int i = 0; i < _num_textures; ++i) { TextureStage *stage = texture->get_on_stage(i); if (!tex_gen->has_stage(stage)) { - texcoord_freg.push_back(alloc_freg()); - text << "\t in float4 vtx_texcoord" << i << " : " << alloc_vreg() << ",\n"; - text << "\t out float4 l_texcoord" << i << " : " << texcoord_freg[i] << ",\n"; - } else { - texcoord_freg.push_back(NULL); + const InternalName *texcoord_name = stage->get_texcoord_name(); + + if (texcoord_fregs.count(texcoord_name) == 0) { + char *freg = alloc_freg(); + string tcname = texcoord_name->join("_"); + texcoord_fregs[texcoord_name] = freg; + + text << "\t in float4 vtx_" << tcname << " : " << alloc_vreg() << ",\n"; + text << "\t out float4 l_" << tcname << " : " << freg << ",\n"; + } + } + + if ((_map_index_normal == i && _lighting && _auto_normal_on) || _map_index_height == i) { + const InternalName *texcoord_name = stage->get_texcoord_name(); + PT(InternalName) tangent_name = InternalName::get_tangent(); + PT(InternalName) binormal_name = InternalName::get_binormal(); + + if (texcoord_name != InternalName::get_texcoord()) { + tangent_name = tangent_name->append(texcoord_name->get_basename()); + binormal_name = binormal_name->append(texcoord_name->get_basename()); + } + tangent_input = tangent_name->join("_"); + binormal_input = binormal_name->join("_"); + + text << "\t in float4 vtx_" << tangent_input << " : " << alloc_vreg() << ",\n"; + text << "\t in float4 vtx_" << binormal_input << " : " << alloc_vreg() << ",\n"; + + if (_map_index_normal == i && _lighting && _auto_normal_on) { + tangent_freg = alloc_freg(); + binormal_freg = alloc_freg(); + text << "\t out float4 l_tangent : " << tangent_freg << ",\n"; + text << "\t out float4 l_binormal : " << binormal_freg << ",\n"; + } } } if (_vertex_colors) { @@ -695,49 +721,27 @@ synthesize_shader(const RenderState *rs) { text << "\t in float4 vtx_normal : NORMAL,\n"; } if (_map_index_height >= 0) { - htangent_vreg = alloc_vreg(); - hbinormal_vreg = alloc_vreg(); - if (_map_index_normal == _map_index_height) { - ntangent_vreg = htangent_vreg; - nbinormal_vreg = hbinormal_vreg; - } - text << "\t in float4 vtx_tangent" << _map_index_height << " : " << htangent_vreg << ",\n"; - text << "\t in float4 vtx_binormal" << _map_index_height << " : " << hbinormal_vreg << ",\n"; text << "\t uniform float4 mspos_view,\n"; text << "\t out float3 l_eyevec,\n"; } if (_lighting) { - if (_map_index_normal >= 0 && _auto_normal_on) { - // If we had a height map and it used the same stage, that means we already have those inputs. - if (_map_index_normal != _map_index_height) { - ntangent_vreg = alloc_vreg(); - nbinormal_vreg = alloc_vreg(); - // NB. If we used TANGENT and BINORMAL, Cg would have them overlap with TEXCOORD6-7. - text << "\t in float4 vtx_tangent" << _map_index_normal << " : " << ntangent_vreg << ",\n"; - text << "\t in float4 vtx_binormal" << _map_index_normal << " : " << nbinormal_vreg << ",\n"; - } - ntangent_freg = alloc_freg(); - nbinormal_freg = alloc_freg(); - text << "\t out float4 l_tangent : " << ntangent_freg << ",\n"; - text << "\t out float4 l_binormal : " << nbinormal_freg << ",\n"; - } if (_shadows && _auto_shadow_on) { for (int i=0; i < (int)_dlights.size(); i++) { if (_dlights[i]->_shadow_caster) { - dlightcoord_freg.push_back(alloc_freg()); + dlightcoord_fregs.push_back(alloc_freg()); text << "\t uniform float4x4 trans_model_to_clip_of_dlight" << i << ",\n"; - text << "\t out float4 l_dlightcoord" << i << " : " << dlightcoord_freg[i] << ",\n"; + text << "\t out float4 l_dlightcoord" << i << " : " << dlightcoord_fregs[i] << ",\n"; } else { - dlightcoord_freg.push_back(NULL); + dlightcoord_fregs.push_back(NULL); } } for (int i=0; i < (int)_slights.size(); i++) { if (_slights[i]->_shadow_caster) { - slightcoord_freg.push_back(alloc_freg()); + slightcoord_fregs.push_back(alloc_freg()); text << "\t uniform float4x4 trans_model_to_clip_of_slight" << i << ",\n"; - text << "\t out float4 l_slightcoord" << i << " : " << slightcoord_freg[i] << ",\n"; + text << "\t out float4 l_slightcoord" << i << " : " << slightcoord_fregs[i] << ",\n"; } else { - slightcoord_freg.push_back(NULL); + slightcoord_fregs.push_back(NULL); } } } @@ -768,18 +772,19 @@ synthesize_shader(const RenderState *rs) { text << "\t l_eye_normal.xyz = mul((float3x3)tpose_view_to_model, vtx_normal.xyz);\n"; text << "\t l_eye_normal.w = 0;\n"; } - for (int i = 0; i < _num_textures; ++i) { - if (!tex_gen->has_stage(texture->get_on_stage(i))) { - text << "\t l_texcoord" << i << " = vtx_texcoord" << i << ";\n"; - } + pmap::const_iterator it; + for (it = texcoord_fregs.begin(); it != texcoord_fregs.end(); ++it) { + // Pass through all texcoord inputs as-is. + string tcname = it->first->join("_"); + text << "\t l_" << tcname << " = vtx_" << tcname << ";\n"; } if (_vertex_colors) { text << "\t l_color = vtx_color;\n"; } if (_lighting && (_map_index_normal >= 0 && _auto_normal_on)) { - text << "\t l_tangent.xyz = mul((float3x3)tpose_view_to_model, vtx_tangent" << _map_index_normal << ".xyz);\n"; + text << "\t l_tangent.xyz = mul((float3x3)tpose_view_to_model, vtx_" << tangent_input << ".xyz);\n"; text << "\t l_tangent.w = 0;\n"; - text << "\t l_binormal.xyz = mul((float3x3)tpose_view_to_model, -vtx_binormal" << _map_index_normal << ".xyz);\n"; + text << "\t l_binormal.xyz = mul((float3x3)tpose_view_to_model, -vtx_" << binormal_input << ".xyz);\n"; text << "\t l_binormal.w = 0;\n"; } if (_shadows && _auto_shadow_on) { @@ -824,22 +829,22 @@ synthesize_shader(const RenderState *rs) { if (_need_eye_normal) { text << "\t in float4 l_eye_normal : " << eye_normal_freg << ",\n"; } + for (it = texcoord_fregs.begin(); it != texcoord_fregs.end(); ++it) { + text << "\t in float4 l_" << it->first->join("_") << " : " << it->second << ",\n"; + } const TexMatrixAttrib *tex_matrix = DCAST(TexMatrixAttrib, rs->get_attrib_def(TexMatrixAttrib::get_class_slot())); for (int i=0; i<_num_textures; i++) { TextureStage *stage = texture->get_on_stage(i); Texture *tex = texture->get_on_texture(stage); nassertr(tex != NULL, NULL); text << "\t uniform sampler" << texture_type_as_string(tex->get_texture_type()) << " tex_" << i << ",\n"; - if (!tex_gen->has_stage(stage)) { - text << "\t in float4 l_texcoord" << i << " : " << texcoord_freg[i] << ",\n"; - } if (tex_matrix->has_stage(stage)) { text << "\t uniform float4x4 texmat_" << i << ",\n"; } } if (_lighting && (_map_index_normal >= 0 && _auto_normal_on)) { - text << "\t in float3 l_tangent : " << ntangent_freg << ",\n"; - text << "\t in float3 l_binormal : " << nbinormal_freg << ",\n"; + text << "\t in float3 l_tangent : " << tangent_freg << ",\n"; + text << "\t in float3 l_binormal : " << binormal_freg << ",\n"; } if (_lighting) { for (int i=0; i < (int)_alights.size(); i++) { @@ -853,7 +858,7 @@ synthesize_shader(const RenderState *rs) { } else { text << "\t uniform sampler2D k_dlighttex" << i << ",\n"; } - text << "\t in float4 l_dlightcoord" << i << " : " << dlightcoord_freg[i] << ",\n"; + text << "\t in float4 l_dlightcoord" << i << " : " << dlightcoord_fregs[i] << ",\n"; } } for (int i=0; i < (int)_plights.size(); i++) { @@ -868,7 +873,7 @@ synthesize_shader(const RenderState *rs) { } else { text << "\t uniform sampler2D k_slighttex" << i << ",\n"; } - text << "\t in float4 l_slightcoord" << i << " : " << slightcoord_freg[i] << ",\n"; + text << "\t in float4 l_slightcoord" << i << " : " << slightcoord_fregs[i] << ",\n"; } } if (_need_material_props) { @@ -916,26 +921,30 @@ synthesize_shader(const RenderState *rs) { if (tex_gen != NULL && tex_gen->has_stage(stage)) { switch (tex_gen->get_mode(stage)) { case TexGenAttrib::M_world_position: - text << "\t float4 l_texcoord" << i << " = l_world_position;\n"; + text << "\t float4 texcoord" << i << " = l_world_position;\n"; break; case TexGenAttrib::M_world_normal: - text << "\t float4 l_texcoord" << i << " = l_world_normal;\n"; + text << "\t float4 texcoord" << i << " = l_world_normal;\n"; break; case TexGenAttrib::M_eye_position: - text << "\t float4 l_texcoord" << i << " = l_eye_position;\n"; + text << "\t float4 texcoord" << i << " = l_eye_position;\n"; break; case TexGenAttrib::M_eye_normal: - text << "\t float4 l_texcoord" << i << " = l_eye_normal;\n"; - text << "\t l_texcoord" << i << ".w = 1.0f;\n"; + text << "\t float4 texcoord" << i << " = l_eye_normal;\n"; + text << "\t texcoord" << i << ".w = 1.0f;\n"; break; default: pgraph_cat.error() << "Unsupported TexGenAttrib mode\n"; - text << "\t float4 l_texcoord" << i << " = float4(0, 0, 0, 0);\n"; + text << "\t float4 texcoord" << i << " = float4(0, 0, 0, 0);\n"; } + } else { + // Cg seems to be able to optimize this temporary away when appropriate. + const InternalName *texcoord_name = stage->get_texcoord_name(); + text << "\t float4 texcoord" << i << " = l_" << texcoord_name->join("_") << ";\n"; } if (tex_matrix != NULL && tex_matrix->has_stage(stage)) { - text << "\t l_texcoord" << i << " = mul(texmat_" << i << ", l_texcoord" << i << ");\n"; - text << "\t l_texcoord" << i << ".xyz /= l_texcoord" << i << ".w;\n"; + text << "\t texcoord" << i << " = mul(texmat_" << i << ", texcoord" << i << ");\n"; + text << "\t texcoord" << i << ".xyz /= texcoord" << i << ".w;\n"; } } text << "\t // Fetch all textures.\n"; @@ -943,7 +952,7 @@ synthesize_shader(const RenderState *rs) { Texture *tex = texture->get_on_texture(texture->get_on_stage(_map_index_height)); nassertr(tex != NULL, NULL); text << "\t float4 tex" << _map_index_height << " = tex" << texture_type_as_string(tex->get_texture_type()); - text << "(tex_" << _map_index_height << ", l_texcoord" << _map_index_height << "."; + text << "(tex_" << _map_index_height << ", texcoord" << _map_index_height << "."; switch (tex->get_texture_type()) { case Texture::TT_cube_map: case Texture::TT_3d_texture: @@ -983,21 +992,21 @@ synthesize_shader(const RenderState *rs) { nassertr(tex != NULL, NULL); // Parallax mapping pushes the texture coordinates of the other textures away from the camera. if (_map_index_height >= 0 && parallax_mapping_samples > 0) { - text << "\t l_texcoord" << i << ".xyz -= parallax_offset;\n"; + text << "\t texcoord" << i << ".xyz -= parallax_offset;\n"; } text << "\t float4 tex" << i << " = tex" << texture_type_as_string(tex->get_texture_type()); - text << "(tex_" << i << ", l_texcoord" << i << "."; + text << "(tex_" << i << ", texcoord" << i << "."; switch(tex->get_texture_type()) { case Texture::TT_cube_map: case Texture::TT_3d_texture: case Texture::TT_2d_texture_array: - text << "xyz"; + text << "xyz"; break; - case Texture::TT_2d_texture: + case Texture::TT_2d_texture: text << "xy"; break; - case Texture::TT_1d_texture: - text << "x"; + case Texture::TT_1d_texture: + text << "x"; break; default: break; @@ -1240,7 +1249,7 @@ synthesize_shader(const RenderState *rs) { } else if (_flat_colors) { text << "\t result = attr_color;\n"; } else { - text << "\t result = float4(1,1,1,1);\n"; + text << "\t result = float4(1, 1, 1, 1);\n"; } } diff --git a/panda/src/pgraphnodes/shaderGenerator.h b/panda/src/pgraphnodes/shaderGenerator.h index 0c588df8a1..d08a3976a8 100644 --- a/panda/src/pgraphnodes/shaderGenerator.h +++ b/panda/src/pgraphnodes/shaderGenerator.h @@ -86,8 +86,8 @@ protected: int _vtregs_used; int _ftregs_used; void reset_register_allocator(); - INLINE char *alloc_vreg(); - INLINE char *alloc_freg(); + char *alloc_vreg(); + char *alloc_freg(); // RenderState analysis information. Created by analyze_renderstate: