From 3d05d84d8799a5e551f9e7f9a65f13b0f493c9ca Mon Sep 17 00:00:00 2001 From: Zhao Huang Date: Tue, 13 Nov 2012 02:45:44 +0000 Subject: [PATCH] Added support for shorthand shaderinput lexicons like mspos_camshadow and trans_model_to_clip_of_camshadow to GLSL. --- panda/src/glstuff/glShaderContext_src.cxx | 163 ++++++++++++++++++++++ panda/src/glstuff/glShaderContext_src.h | 2 +- panda/src/gobj/shader.h | 2 +- 3 files changed, 165 insertions(+), 2 deletions(-) diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 5c5d21032f..0894791394 100755 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -47,6 +47,164 @@ TypeHandle CLP(ShaderContext)::_type_handle; #endif #endif + +//////////////////////////////////////////////////////////////////// +// Function: GLShaderContext::ParseAndSetShaderUniformVars +// Access: Public +// Description: The Panda CG shader syntax defines a useful set of shorthand notations for setting nodepath +// properties as shaderinputs. For example, float4 mspos_XXX refers to nodepath XXX's position +// in model space. This function is a rough attempt to reimplement some of the shorthand +// notations for GLSL. The code is ~99% composed of excerpts dealing with matrix shaderinputs +// from Shader::compile_parameter. +// +// Given a uniform variable name queried from the compiled shader passed in via arg_id, +// 1) parse the name +// 2a) if the name refers to a Panda shorthand notation +// push the appropriate matrix into shader._mat_spec +// returns True +// 2b) If the name doesn't refer to a Panda shorthand notation +// returns False +// +// The boolean return is used to notify down-river processing whether the shader var/parm was +// actually picked up and the appropriate ShaderMatSpec pushed onto _mat_spec. +//////////////////////////////////////////////////////////////////// +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"); + pieces.push_back("model"); + } + if (pieces[0] == "wstrans") { + pieces[0] = "trans"; + pieces.push_back("to"); + pieces.push_back("world"); + } + if (pieces[0] == "vstrans") { + pieces[0] = "trans"; + pieces.push_back("to"); + pieces.push_back("view"); + } + if (pieces[0] == "cstrans") { + pieces[0] = "trans"; + pieces.push_back("to"); + pieces.push_back("clip"); + } + if (pieces[0] == "mspos") { + pieces[0] = "row3"; + pieces.push_back("to"); + pieces.push_back("model"); + } + if (pieces[0] == "wspos") { + pieces[0] = "row3"; + pieces.push_back("to"); + pieces.push_back("world"); + } + if (pieces[0] == "vspos") { + pieces[0] = "row3"; + pieces.push_back("to"); + pieces.push_back("view"); + } + if (pieces[0] == "cspos") { + pieces[0] = "row3"; + pieces.push_back("to"); + pieces.push_back("clip"); + } + + if ((pieces[0] == "mat")||(pieces[0] == "inv")|| + (pieces[0] == "tps")||(pieces[0] == "itp")) { + if (!objShader->cp_errchk_parameter_words(p, 2)) { + return false; + } + string trans = pieces[0]; + string matrix = pieces[1]; + pieces.clear(); + if (matrix == "modelview") { + tokenize("trans_model_to_apiview", pieces, "_"); + } else if (matrix == "projection") { + tokenize("trans_apiview_to_apiclip", pieces, "_"); + } else if (matrix == "modelproj") { + tokenize("trans_model_to_apiclip", pieces, "_"); + } else { + objShader->cp_report_error(p,"unrecognized matrix name"); + return false; + } + if (trans=="mat") { + pieces[0] = "trans"; + } else if (trans=="inv") { + string t = pieces[1]; + pieces[1] = pieces[3]; + pieces[3] = t; + } else if (trans=="tps") { + pieces[0] = "tpose"; + } 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")) { + + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._func = Shader::SMF_compose; + + int next = 1; + 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 (!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; + } + objShader->cp_optimize_mat_spec(bind); + objShader->_mat_spec.push_back(bind); + return true; + } + return false; +} + //////////////////////////////////////////////////////////////////// // Function: GLShaderContext::Constructor // Access: Public @@ -205,6 +363,11 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { continue; } + //Tries to parse shorthand notations like mspos_XXX and trans_model_to_clip_of_XXX + if (parse_and_set_short_hand_shader_vars( arg_id, s )) { + continue; + } + if (param_size==1) { switch (param_type) { #ifndef OPENGLES diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index 85d077bafe..2038473317 100755 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -76,7 +76,7 @@ private: void glsl_report_program_errors(GSG *gsg, unsigned int program); unsigned int glsl_compile_entry_point(GSG *gsg, Shader::ShaderType type); bool glsl_compile_shader(GSG *gsg); - + bool parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *s); void release_resources(GSG *gsg); public: diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index ec63983e2e..54f0fb6456 100755 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -399,7 +399,7 @@ public: string _tess_evaluation; }; - private: + public: // These routines help split the shader into sections, // for those shader implementations that need to do so. // Don't use them when you use separate shader programs.