Add support for k_time / osg_FrameTime inputs, and change the Shader Generator not to require a separate texcoord set for every texture in an effort to cut down on register overuse.

This commit is contained in:
rdb 2014-02-10 11:32:06 +00:00
parent 89749133ff
commit 4da840805f
6 changed files with 271 additions and 215 deletions

View File

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

View File

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

View File

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

View File

@ -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<CGparameter> &map);
#endif
public:
pvector <ShaderPtrSpec> _ptr_spec;
pvector <ShaderPtrSpec> _ptr_spec;
epvector <ShaderMatSpec> _mat_spec;
pvector <ShaderTexSpec> _tex_spec;
pvector <ShaderVarSpec> _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 <PreparedGraphicsObjects *, ShaderContext *> Contexts;
Contexts _contexts;
private:
private:
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
Shader();

View File

@ -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<char *> texcoord_freg;
pvector<char *> dlightcoord_freg;
pvector<char *> slightcoord_freg;
char *tangent_freg = 0;
char *binormal_freg = 0;
string tangent_input;
string binormal_input;
pmap<const InternalName *, char *> texcoord_fregs;
pvector<char *> dlightcoord_fregs;
pvector<char *> 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 InternalName *, char *>::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";
}
}

View File

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