Added support for shorthand shaderinput lexicons like mspos_camshadow and

trans_model_to_clip_of_camshadow to GLSL.
This commit is contained in:
Zhao Huang 2012-11-13 02:45:44 +00:00
parent 4166327919
commit 3d05d84d87
3 changed files with 165 additions and 2 deletions

View File

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

View File

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

View File

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