diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 4bd7c76abc..5809ded96b 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -2,6 +2,7 @@ // Created by: drose (25Feb02) // Updated by: fperazzi, PandaSE (06Apr10) (added more overloads // for set_shader_input) +// Updated by: weifengh, PandaSE(15Apr10) (added set_shader_auto) // //////////////////////////////////////////////////////////////////// // @@ -3717,6 +3718,29 @@ set_shader_auto(int priority) { } } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_shader_auto +// Access: Published +// Description: overloaded for auto shader selective on/off of +// normal, glow, gloss, ramp, shadow +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_shader_auto(const char* normal_on, const char* glow_on, const char* gloss_on, const char* ramp_on, const char* shadow_on, int priority) { + nassertv_always(!is_empty()); + + const RenderAttrib *attrib = + node()->get_attrib(ShaderAttrib::get_class_slot()); + if (attrib != (const RenderAttrib *)NULL) { + priority = max(priority, + node()->get_state()->get_override(ShaderAttrib::get_class_slot())); + const ShaderAttrib *sa = DCAST(ShaderAttrib, attrib); + node()->set_attrib(sa->set_shader_auto(normal_on, glow_on, gloss_on, ramp_on, shadow_on, priority)); + } else { + // Create a new ShaderAttrib for this node. + CPT(ShaderAttrib) sa = DCAST(ShaderAttrib, ShaderAttrib::make()); + node()->set_attrib(sa->set_shader_auto(normal_on, glow_on, gloss_on, ramp_on, shadow_on, priority)); + } +} //////////////////////////////////////////////////////////////////// // Function: NodePath::clear_shader // Access: Published diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index fcd8fd8d0b..1b87bc21c4 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -2,6 +2,7 @@ // Created by: drose (25Feb02) // Updated by: fperazzi, PandaSE (06Apr10) (added more overloads // for set_shader_input) +// Updated by: weifengh, PandaSE(15Apr10) // //////////////////////////////////////////////////////////////////// // @@ -604,6 +605,7 @@ PUBLISHED: void set_shader(const Shader *sha, int priority = 0); void set_shader_off(int priority = 0); void set_shader_auto(int priority = 0); + void set_shader_auto(const char* normal_on, const char* glow_on, const char* gloss_on, const char* ramp_on, const char* shadow_on, int priority=0); void clear_shader(); void set_shader_input(const ShaderInput *inp); diff --git a/panda/src/pgraph/shaderAttrib.I b/panda/src/pgraph/shaderAttrib.I index 2bffe79a96..488e3691e8 100755 --- a/panda/src/pgraph/shaderAttrib.I +++ b/panda/src/pgraph/shaderAttrib.I @@ -1,5 +1,6 @@ // Filename: shaderAttrib.I // Created by: sshodhan (10Jul04) +// Updated by: weifengh, PandaSE(15Apr10) // //////////////////////////////////////////////////////////////////// // @@ -26,7 +27,12 @@ ShaderAttrib() : _has_shader(false), _flags(0), _has_flags(0), - _instance_count(0) + _instance_count(0), + _auto_normal_on(false), + _auto_glow_on(false), + _auto_gloss_on(false), + _auto_ramp_on(false), + _auto_shadow_on(false) { } @@ -44,7 +50,12 @@ ShaderAttrib(const ShaderAttrib ©) : _flags(copy._flags), _has_flags(copy._has_flags), _instance_count(copy._instance_count), - _inputs(copy._inputs) + _inputs(copy._inputs), + _auto_normal_on(copy._auto_normal_on), + _auto_glow_on(copy._auto_glow_on), + _auto_gloss_on(copy._auto_gloss_on), + _auto_ramp_on(copy._auto_ramp_on), + _auto_shadow_on(copy._auto_shadow_on) { } @@ -102,3 +113,53 @@ get_flag(int index) const { return (_flags & (1<_shader = NULL; result->_shader_priority = priority; result->_auto_shader = false; + result->_auto_normal_on = false; + result->_auto_glow_on = false; + result->_auto_gloss_on = false; + result->_auto_ramp_on = false; + result->_auto_shadow_on = false; + result->_has_shader = true; return return_new(result); } @@ -113,6 +121,42 @@ set_shader_auto(int priority) const { result->_shader_priority = priority; result->_auto_shader = true; result->_has_shader = true; + result->_auto_normal_on = true; + result->_auto_glow_on = true; + result->_auto_gloss_on = true; + result->_auto_ramp_on = true; + result->_auto_shadow_on = true; + return return_new(result); +} + +//////////////////////////////////////////////////////////////////// +// Function: ShaderAttrib::set_shader_auto +// Access: Published +// Description: Set auto shader with control over whether to keep +// normal, glow, etc., on or off (e.g., all on via +// "normal-on","glow-on","gloss-on","ramp-on","shadow-on") +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ShaderAttrib:: +set_shader_auto(const char* normal_on, const char* glow_on, const char* gloss_on, const char* ramp_on, const char* shadow_on, int priority) const { + + ShaderAttrib *result = new ShaderAttrib(*this); + result->_shader = NULL; + result->_shader_priority = priority; + result->_auto_shader = true; + result->_has_shader = true; + string cleanedFlag; + + cleanedFlag = downcase(normal_on); + result->_auto_normal_on = (cleanedFlag == "normal_on"); + cleanedFlag = downcase(glow_on); + result->_auto_glow_on = (cleanedFlag == "glow_on"); + cleanedFlag = downcase(gloss_on); + result->_auto_gloss_on = (cleanedFlag == "gloss_on"); + cleanedFlag = downcase(ramp_on); + result->_auto_ramp_on = (cleanedFlag == "ramp_on"); + cleanedFlag = downcase(shadow_on); + result->_auto_shadow_on = (cleanedFlag == "shadow_on"); + return return_new(result); } @@ -128,6 +172,11 @@ clear_shader() const { result->_shader_priority = 0; result->_auto_shader = false; result->_has_shader = false; + result->_auto_normal_on = false; + result->_auto_glow_on = false; + result->_auto_gloss_on = false; + result->_auto_ramp_on = false; + result->_auto_shadow_on = false; return return_new(result); } @@ -723,7 +772,22 @@ compare_to_impl(const RenderAttrib *other) const { if (this->_instance_count != that->_instance_count) { return (this->_instance_count < that->_instance_count) ? -1 : 1; } - + if (this->_auto_normal_on != that->_auto_normal_on) { + return (this->_auto_normal_on < that->_auto_normal_on) ? -1 : 1; + } + if (this->_auto_glow_on != that->_auto_glow_on) { + return (this->_auto_glow_on < that->_auto_glow_on) ? -1 : 1; + } + if (this->_auto_gloss_on != that->_auto_gloss_on) { + return (this->_auto_gloss_on < that->_auto_gloss_on) ? -1 : 1; + } + if (this->_auto_ramp_on != that->_auto_ramp_on) { + return (this->_auto_ramp_on < that->_auto_ramp_on) ? -1 : 1; + } + if (this->_auto_shadow_on != that->_auto_shadow_on) { + return (this->_auto_shadow_on < that->_auto_shadow_on) ? -1 : 1; + } + Inputs::const_iterator i1 = this->_inputs.begin(); Inputs::const_iterator i2 = that->_inputs.begin(); while ((i1 != this->_inputs.end()) && (i2 != that->_inputs.end())) { @@ -761,6 +825,11 @@ compose_impl(const RenderAttrib *other) const { attr->_shader_priority = over->_shader_priority; attr->_auto_shader = over->_auto_shader; attr->_has_shader = over->_has_shader; + attr->_auto_normal_on = over->_auto_normal_on; + attr->_auto_glow_on = over->_auto_glow_on; + attr->_auto_gloss_on = over->_auto_gloss_on; + attr->_auto_ramp_on = over->_auto_ramp_on; + attr->_auto_shadow_on = over->_auto_shadow_on; } } // Update the shader-data portion. diff --git a/panda/src/pgraph/shaderAttrib.h b/panda/src/pgraph/shaderAttrib.h index c1542a2806..7bba68ce91 100755 --- a/panda/src/pgraph/shaderAttrib.h +++ b/panda/src/pgraph/shaderAttrib.h @@ -2,6 +2,7 @@ // Created by: jyelon (01Sep05) // Updated by: fperazzi, PandaSE (06Apr10) (added more overloads // for set_shader_input) +// Updated by: weifengh, PandaSE(15Apr10) // //////////////////////////////////////////////////////////////////// // @@ -55,10 +56,18 @@ PUBLISHED: INLINE bool auto_shader() const; INLINE int get_shader_priority() const; INLINE int get_instance_count() const; - + INLINE bool auto_normal_on() const; + INLINE bool auto_glow_on() const; + INLINE bool auto_gloss_on() const; + INLINE bool auto_ramp_on() const; + INLINE bool auto_shadow_on() const; + CPT(RenderAttrib) set_shader(const Shader *s, int priority=0) const; CPT(RenderAttrib) set_shader_off(int priority=0) const; CPT(RenderAttrib) set_shader_auto(int priority=0) const; + + CPT(RenderAttrib) set_shader_auto(const char* normal_on, const char* glow_on, const char* gloss_on, const char* ramp_on, const char* shadow_on, int priority=0) const; + CPT(RenderAttrib) clear_shader() const; // Shader Inputs CPT(RenderAttrib) set_shader_input(const ShaderInput *inp) const; @@ -136,6 +145,13 @@ private: int _flags; int _has_flags; int _instance_count; + + bool _auto_normal_on; + bool _auto_glow_on; + bool _auto_gloss_on; + bool _auto_ramp_on; + bool _auto_shadow_on; + typedef pmap < CPT(InternalName), CPT(ShaderInput) > Inputs; Inputs _inputs; diff --git a/panda/src/pgraphnodes/shaderGenerator.cxx b/panda/src/pgraphnodes/shaderGenerator.cxx index 909f23b5fa..2fcbda5750 100644 --- a/panda/src/pgraphnodes/shaderGenerator.cxx +++ b/panda/src/pgraphnodes/shaderGenerator.cxx @@ -1,5 +1,6 @@ // Filename: shaderGenerator.cxx // Created by: jyelon (15Dec07) +// Updated by: weifengh, PandaSE(15Apr10) // //////////////////////////////////////////////////////////////////// // @@ -427,6 +428,15 @@ analyze_renderstate(const RenderState *rs) { _need_world_position = true; } + const ShaderAttrib *shader_attrib = DCAST(ShaderAttrib, rs->get_attrib_def(ShaderAttrib::get_class_slot())); + if (shader_attrib->auto_shader()) { + _auto_normal_on = shader_attrib->auto_normal_on(); + _auto_glow_on = shader_attrib->auto_glow_on(); + _auto_gloss_on = shader_attrib->auto_gloss_on(); + _auto_ramp_on = shader_attrib->auto_ramp_on(); + _auto_shadow_on = shader_attrib->auto_shadow_on(); + } + // Check for unimplemented features and issue warnings. const FogAttrib *fog = DCAST(FogAttrib, rs->get_attrib_def(FogAttrib::get_class_slot())); if (!fog->is_off()) { @@ -474,6 +484,12 @@ clear_analysis() { _need_world_normal = false; _need_eye_position = false; _need_eye_normal = false; + _auto_normal_on = false; + _auto_glow_on = false; + _auto_gloss_on = false; + _auto_ramp_on = false; + _auto_shadow_on = false; + _alights.clear(); _dlights.clear(); _plights.clear(); @@ -682,7 +698,7 @@ synthesize_shader(const RenderState *rs) { text << "\t out float3 l_eyevec,\n"; } if (_lighting) { - if (_map_index_normal >= 0) { + 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(); @@ -695,7 +711,7 @@ synthesize_shader(const RenderState *rs) { text << "\t out float4 l_tangent : " << ntangent_freg << ",\n"; text << "\t out float4 l_binormal : " << nbinormal_freg << ",\n"; } - if (_shadows) { + if (_shadows && _auto_shadow_on) { for (int i=0; i<(int)_dlights.size(); i++) { if (_dlights[i]->_shadow_caster) { text << "\t uniform float4x4 trans_model_to_clip_of_dlight" << i << ",\n"; @@ -737,13 +753,13 @@ synthesize_shader(const RenderState *rs) { if (_vertex_colors) { text << "\t l_color = vtx_color;\n"; } - if (_lighting && (_map_index_normal >= 0)) { + 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.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.w = 0;\n"; } - if (_shadows) { + if (_shadows && _auto_shadow_on) { text << "\t float4x4 biasmat = {0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f};\n"; for (int i=0; i<(int)_dlights.size(); i++) { if (_dlights[i]->_shadow_caster) { @@ -791,7 +807,7 @@ synthesize_shader(const RenderState *rs) { text << "\t uniform float4x4 texmat_" << i << ",\n"; } } - if (_lighting && (_map_index_normal >= 0)) { + 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"; } @@ -801,7 +817,7 @@ synthesize_shader(const RenderState *rs) { } for (int i=0; i<(int)_dlights.size(); i++) { text << "\t uniform float4x4 dlight_dlight" << i << "_rel_view,\n"; - if (_shadows && _dlights[i]->_shadow_caster) { + if (_shadows && _dlights[i]->_shadow_caster && _auto_shadow_on) { if (_use_shadow_filter) { text << "\t uniform sampler2DShadow k_dlighttex" << i << ",\n"; } else { @@ -816,7 +832,7 @@ synthesize_shader(const RenderState *rs) { for (int i=0; i<(int)_slights.size(); i++) { text << "\t uniform float4x4 slight_slight" << i << "_rel_view,\n"; text << "\t uniform float4 satten_slight" << i << ",\n"; - if (_shadows && _slights[i]->_shadow_caster) { + if (_shadows && _slights[i]->_shadow_caster && _auto_shadow_on) { if (_use_shadow_filter) { text << "\t uniform sampler2DShadow k_slighttex" << i << ",\n"; } else { @@ -942,7 +958,7 @@ synthesize_shader(const RenderState *rs) { } } if (_lighting) { - if (_map_index_normal >= 0) { + if (_map_index_normal >= 0 && _auto_normal_on) { text << "\t // Translate tangent-space normal in map to view-space.\n"; text << "\t float3 tsnormal = ((float3)tex" << _map_index_normal << " * 2) - 1;\n"; text << "\t l_eye_normal.xyz *= tsnormal.z;\n"; @@ -962,7 +978,7 @@ synthesize_shader(const RenderState *rs) { text << "\t // Begin view-space light calculations\n"; text << "\t float ldist,lattenv,langle;\n"; text << "\t float4 lcolor,lspec,lvec,lpoint,latten,ldir,leye,lhalf;"; - if (_shadows) { + if (_shadows && _auto_shadow_on) { text << "\t float lshad;\n"; } if (_separate_ambient_diffuse) { @@ -1000,7 +1016,7 @@ synthesize_shader(const RenderState *rs) { text << "\t lspec = dlight_dlight" << i << "_rel_view[1];\n"; text << "\t lvec = dlight_dlight" << i << "_rel_view[2];\n"; text << "\t lcolor *= saturate(dot(l_eye_normal.xyz, lvec.xyz));\n"; - if (_shadows && _dlights[i]->_shadow_caster) { + if (_shadows && _dlights[i]->_shadow_caster && _auto_shadow_on) { if (_use_shadow_filter) { text << "\t lshad = shadow2DProj(k_dlighttex" << i << ", l_dlightcoord" << i << ").r;\n"; } else { @@ -1062,7 +1078,7 @@ synthesize_shader(const RenderState *rs) { text << "\t lattenv *= pow(langle, latten.w);\n"; text << "\t if (langle < ldir.w) lattenv = 0;\n"; text << "\t lcolor *= lattenv * saturate(dot(l_eye_normal.xyz, lvec.xyz));\n"; - if (_shadows && _slights[i]->_shadow_caster) { + if (_shadows && _slights[i]->_shadow_caster && _auto_shadow_on) { if (_use_shadow_filter) { text << "\t lshad = shadow2DProj(k_slighttex" << i << ", l_slightcoord" << i << ").r;\n"; } else { @@ -1086,44 +1102,45 @@ synthesize_shader(const RenderState *rs) { text << "\t tot_specular += lspec;\n"; } } - const LightRampAttrib *light_ramp = DCAST(LightRampAttrib, rs->get_attrib_def(LightRampAttrib::get_class_slot())); - switch (light_ramp->get_mode()) { - case LightRampAttrib::LRT_single_threshold: - { - float t = light_ramp->get_threshold(0); - float l0 = light_ramp->get_level(0); - text << "\t // Single-threshold light ramp\n"; - text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n"; - text << "\t float lr_scale = (lr_in < " << t << ") ? 0.0 : (" << l0 << "/lr_in);\n"; - text << "\t tot_diffuse = tot_diffuse * lr_scale;\n"; - break; - } - case LightRampAttrib::LRT_double_threshold: - { - float t0 = light_ramp->get_threshold(0); - float t1 = light_ramp->get_threshold(1); - float l0 = light_ramp->get_level(0); - float l1 = light_ramp->get_level(1); - float l2 = light_ramp->get_level(2); - text << "\t // Double-threshold light ramp\n"; - text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n"; - text << "\t float lr_out = " << l0 << "\n"; - text << "\t if (lr_in > " << t0 << ") lr_out=" << l1 << ";\n"; - text << "\t if (lr_in > " << t1 << ") lr_out=" << l2 << ";\n"; - text << "\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n"; - break; + if(_auto_ramp_on) { + switch (light_ramp->get_mode()) { + case LightRampAttrib::LRT_single_threshold: + { + float t = light_ramp->get_threshold(0); + float l0 = light_ramp->get_level(0); + text << "\t // Single-threshold light ramp\n"; + text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n"; + text << "\t float lr_scale = (lr_in < " << t << ") ? 0.0 : (" << l0 << "/lr_in);\n"; + text << "\t tot_diffuse = tot_diffuse * lr_scale;\n"; + break; + } + case LightRampAttrib::LRT_double_threshold: + { + float t0 = light_ramp->get_threshold(0); + float t1 = light_ramp->get_threshold(1); + float l0 = light_ramp->get_level(0); + float l1 = light_ramp->get_level(1); + float l2 = light_ramp->get_level(2); + text << "\t // Double-threshold light ramp\n"; + text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n"; + text << "\t float lr_out = " << l0 << "\n"; + text << "\t if (lr_in > " << t0 << ") lr_out=" << l1 << ";\n"; + text << "\t if (lr_in > " << t1 << ") lr_out=" << l2 << ";\n"; + text << "\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n"; + break; + } } } text << "\t // Begin view-space light summation\n"; if (_have_emission) { - if (_map_index_glow >= 0) { + if (_map_index_glow >= 0 && _auto_glow_on) { text << "\t result = attr_material[2] * saturate(2 * (tex" << _map_index_glow << ".a - 0.5));\n"; } else { text << "\t result = attr_material[2];\n"; } } else { - if (_map_index_glow >= 0) { + if (_map_index_glow >= 0 && _auto_glow_on) { text << "\t result = saturate(2 * (tex" << _map_index_glow << ".a - 0.5));\n"; } else { text << "\t result = float4(0,0,0,0);\n"; @@ -1269,14 +1286,14 @@ synthesize_shader(const RenderState *rs) { } if (_out_primary_glow) { - if (_map_index_glow >= 0) { + if (_map_index_glow >= 0 && _auto_glow_on) { text << "\t result.a = tex" << _map_index_glow << ".a;\n"; } else { text << "\t result.a = 0.5;\n"; } } if (_out_aux_glow) { - if (_map_index_glow >= 0) { + if (_map_index_glow >= 0 && _auto_glow_on) { text << "\t o_aux.a = tex" << _map_index_glow << ".a;\n"; } else { text << "\t o_aux.a = 0.5;\n"; @@ -1288,25 +1305,26 @@ synthesize_shader(const RenderState *rs) { if (_material->has_specular()) { text << "\t tot_specular *= attr_material[3];\n"; } - if (_map_index_gloss >= 0) { + if (_map_index_gloss >= 0 && _auto_gloss_on) { text << "\t tot_specular *= tex" << _map_index_gloss << ".a;\n"; } text << "\t result.rgb = result.rgb + tot_specular.rgb;\n"; } } - - const LightRampAttrib *light_ramp = DCAST(LightRampAttrib, rs->get_attrib_def(LightRampAttrib::get_class_slot())); - switch (light_ramp->get_mode()) { - case LightRampAttrib::LRT_hdr0: - text << "\t result.rgb = (result*result*result + result*result + result) / (result*result*result + result*result + result + 1);\n"; - break; - case LightRampAttrib::LRT_hdr1: - text << "\t result.rgb = (result*result + result) / (result*result + result + 1);\n"; - break; - case LightRampAttrib::LRT_hdr2: - text << "\t result.rgb = result / (result + 1);\n"; - break; - default: break; + if(_auto_ramp_on) { + const LightRampAttrib *light_ramp = DCAST(LightRampAttrib, rs->get_attrib_def(LightRampAttrib::get_class_slot())); + switch (light_ramp->get_mode()) { + case LightRampAttrib::LRT_hdr0: + text << "\t result.rgb = (result*result*result + result*result + result) / (result*result*result + result*result + result + 1);\n"; + break; + case LightRampAttrib::LRT_hdr1: + text << "\t result.rgb = (result*result + result) / (result*result + result + 1);\n"; + break; + case LightRampAttrib::LRT_hdr2: + text << "\t result.rgb = result / (result + 1);\n"; + break; + default: break; + } } // The multiply is a workaround for a radeon driver bug. diff --git a/panda/src/pgraphnodes/shaderGenerator.h b/panda/src/pgraphnodes/shaderGenerator.h index 8d2ca7038d..0bc53ecf41 100644 --- a/panda/src/pgraphnodes/shaderGenerator.h +++ b/panda/src/pgraphnodes/shaderGenerator.h @@ -1,5 +1,6 @@ // Filename: shaderGenerator.h // Created by: jyelon (15Dec07) +// Updated by: weifengh, PandaSE(15Apr10) // //////////////////////////////////////////////////////////////////// // @@ -141,6 +142,11 @@ protected: bool _need_world_normal; bool _need_eye_position; bool _need_eye_normal; + bool _auto_normal_on; + bool _auto_glow_on; + bool _auto_gloss_on; + bool _auto_ramp_on; + bool _auto_shadow_on; void analyze_renderstate(const RenderState *rs); void clear_analysis();