Ver Fonte

Added support for shorthand shaderinput lexicons like mspos_camshadow and
trans_model_to_clip_of_camshadow to GLSL.

Zhao Huang há 13 anos atrás
pai
commit
3d05d84d87

+ 163 - 0
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

+ 1 - 1
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:

+ 1 - 1
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.