Browse Source

Added light ramps and gloss maps

Josh Yelon 18 years ago
parent
commit
005bc25282

+ 3 - 0
panda/src/pgraph/Sources.pp

@@ -61,6 +61,7 @@
     lensNode.I lensNode.h \
     light.I light.h \
     lightAttrib.I lightAttrib.h \
+    lightRampAttrib.I lightRampAttrib.h \
     lightLensNode.I lightLensNode.h \
     lightNode.I lightNode.h \
     loader.I loader.h  \
@@ -172,6 +173,7 @@
     lensNode.cxx \
     light.cxx \
     lightAttrib.cxx \
+    lightRampAttrib.cxx \
     lightLensNode.cxx \
     lightNode.cxx \
     loader.cxx \
@@ -278,6 +280,7 @@
     lensNode.I lensNode.h \
     light.I light.h \
     lightAttrib.I lightAttrib.h \
+    lightRampAttrib.I lightRampAttrib.h \
     lightLensNode.I lightLensNode.h \
     lightNode.I lightNode.h \
     loader.I loader.h \

+ 1 - 0
panda/src/pgraph/attribSlots.I

@@ -26,6 +26,7 @@ INLINE void AttribSlots::
 clear_to_zero() {
   _alpha_test     = NULL;
   _antialias      = NULL;
+  _audio_volume   = NULL;
   _clip_plane     = NULL;
   _color          = NULL;
   _color_blend    = NULL;

+ 15 - 46
panda/src/pgraph/attribSlots.cxx

@@ -47,6 +47,7 @@ initialize_defvals() {
   _defvals._depth_write    = DCAST(DepthWriteAttrib,DepthWriteAttrib::make(DepthWriteAttrib::M_on));
   _defvals._fog            = DCAST(FogAttrib,FogAttrib::make_off());
   _defvals._light          = DCAST(LightAttrib,LightAttrib::make_all_off());
+  _defvals._light_ramp     = DCAST(LightRampAttrib,LightRampAttrib::make_identity());
   _defvals._material       = DCAST(MaterialAttrib,MaterialAttrib::make_off());
   _defvals._render_mode    = DCAST(RenderModeAttrib,RenderModeAttrib::make(RenderModeAttrib::M_unchanged));
   _defvals._rescale_normal = DCAST(RescaleNormalAttrib,RescaleNormalAttrib::make_default());
@@ -75,6 +76,7 @@ initialize_defvals() {
   _defvals._depth_write    = DCAST(DepthWriteAttrib,_defvals._depth_write->make_default());
   _defvals._fog            = DCAST(FogAttrib,_defvals._fog->make_default());
   _defvals._light          = DCAST(LightAttrib,_defvals._light->make_default());
+  _defvals._light_ramp     = DCAST(LightRampAttrib,_defvals._light_ramp->make_default());
   _defvals._material       = DCAST(MaterialAttrib,_defvals._material->make_default());
   _defvals._render_mode    = DCAST(RenderModeAttrib,_defvals._render_mode->make_default());
   _defvals._rescale_normal = DCAST(RescaleNormalAttrib,_defvals._rescale_normal->make_default());
@@ -118,6 +120,7 @@ AttribSlots(const AttribSlots &copy) :
   _depth_write(copy._depth_write),
   _fog(copy._fog),
   _light(copy._light),
+  _light_ramp(copy._light_ramp),
   _material(copy._material),
   _render_mode(copy._render_mode),
   _rescale_normal(copy._rescale_normal),
@@ -153,6 +156,7 @@ operator =(const AttribSlots &src) {
   _depth_write    = src._depth_write;
   _fog            = src._fog;
   _light          = src._light;
+  _light_ramp     = src._light_ramp;
   _material       = src._material;
   _render_mode    = src._render_mode;
   _rescale_normal = src._rescale_normal;
@@ -188,55 +192,20 @@ get_slot(int n) const {
   case 12: return DCAST(RenderAttrib, _depth_write);
   case 13: return DCAST(RenderAttrib, _fog);
   case 14: return DCAST(RenderAttrib, _light);
-  case 15: return DCAST(RenderAttrib, _material);
-  case 16: return DCAST(RenderAttrib, _render_mode);
-  case 17: return DCAST(RenderAttrib, _rescale_normal);
-  case 18: return DCAST(RenderAttrib, _shade_model);
-  case 19: return DCAST(RenderAttrib, _shader);
-  case 20: return DCAST(RenderAttrib, _stencil);
-  case 21: return DCAST(RenderAttrib, _tex_gen);
-  case 22: return DCAST(RenderAttrib, _tex_matrix);
-  case 23: return DCAST(RenderAttrib, _texture);
-  case 24: return DCAST(RenderAttrib, _transparency);
+  case 15: return DCAST(RenderAttrib, _light_ramp);
+  case 16: return DCAST(RenderAttrib, _material);
+  case 17: return DCAST(RenderAttrib, _render_mode);
+  case 18: return DCAST(RenderAttrib, _rescale_normal);
+  case 19: return DCAST(RenderAttrib, _shade_model);
+  case 20: return DCAST(RenderAttrib, _shader);
+  case 21: return DCAST(RenderAttrib, _stencil);
+  case 22: return DCAST(RenderAttrib, _tex_gen);
+  case 23: return DCAST(RenderAttrib, _tex_matrix);
+  case 24: return DCAST(RenderAttrib, _texture);
+  case 25: return DCAST(RenderAttrib, _transparency);
   default:
     nassertr(false, NULL);
     return NULL;
   }
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: AttribSlots::set_slot
-//       Access: Public
-//  Description: set the contents of the nth slot.
-////////////////////////////////////////////////////////////////////
-void AttribSlots::
-set_slot(int n, const RenderAttrib *val) {
-  switch(n) {
-  case  0: _alpha_test     = DCAST(AlphaTestAttrib, val);     break;
-  case  1: _antialias      = DCAST(AntialiasAttrib, val);     break;
-  case  2: _audio_volume   = DCAST(AudioVolumeAttrib, val);   break;
-  case  3: _clip_plane     = DCAST(ClipPlaneAttrib, val);     break;
-  case  4: _color          = DCAST(ColorAttrib, val);         break;
-  case  5: _color_blend    = DCAST(ColorBlendAttrib, val);    break;
-  case  6: _color_scale    = DCAST(ColorScaleAttrib, val);    break;
-  case  7: _color_write    = DCAST(ColorWriteAttrib, val);    break;
-  case  8: _cull_bin       = DCAST(CullBinAttrib, val);       break;
-  case  9: _cull_face      = DCAST(CullFaceAttrib, val);      break;
-  case 10: _depth_offset   = DCAST(DepthOffsetAttrib, val);   break;
-  case 11: _depth_test     = DCAST(DepthTestAttrib, val);     break;
-  case 12: _depth_write    = DCAST(DepthWriteAttrib, val);    break;
-  case 13: _fog            = DCAST(FogAttrib, val);           break;
-  case 14: _light          = DCAST(LightAttrib, val);         break;
-  case 15: _material       = DCAST(MaterialAttrib, val);      break;
-  case 16: _render_mode    = DCAST(RenderModeAttrib, val);    break;
-  case 17: _rescale_normal = DCAST(RescaleNormalAttrib, val); break;
-  case 18: _shade_model    = DCAST(ShadeModelAttrib, val);    break;
-  case 19: _shader         = DCAST(ShaderAttrib, val);        break;
-  case 20: _stencil        = DCAST(StencilAttrib, val);       break;
-  case 21: _tex_gen        = DCAST(TexGenAttrib, val);        break;
-  case 22: _tex_matrix     = DCAST(TexMatrixAttrib, val);     break;
-  case 23: _texture        = DCAST(TextureAttrib, val);       break;
-  case 24: _transparency   = DCAST(TransparencyAttrib, val);  break;
-  default: nassertv(false);
-  }
-}

+ 4 - 3
panda/src/pgraph/attribSlots.h

@@ -26,6 +26,7 @@
 #include "renderAttrib.h"
 #include "alphaTestAttrib.h"
 #include "antialiasAttrib.h"
+#include "audioVolumeAttrib.h"
 #include "clipPlaneAttrib.h"
 #include "colorAttrib.h"
 #include "colorBlendAttrib.h"
@@ -38,6 +39,7 @@
 #include "depthWriteAttrib.h"
 #include "fogAttrib.h"
 #include "lightAttrib.h"
+#include "lightRampAttrib.h"
 #include "materialAttrib.h"
 #include "renderModeAttrib.h"
 #include "rescaleNormalAttrib.h"
@@ -48,7 +50,6 @@
 #include "texGenAttrib.h"
 #include "textureAttrib.h"
 #include "transparencyAttrib.h"
-#include "audioVolumeAttrib.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : AttribSlots
@@ -74,6 +75,7 @@ class EXPCL_PANDA_PGRAPH AttribSlots
   CPT(DepthWriteAttrib)      _depth_write;
   CPT(FogAttrib)             _fog;
   CPT(LightAttrib)           _light;
+  CPT(LightRampAttrib)       _light_ramp;
   CPT(MaterialAttrib)        _material;
   CPT(RenderModeAttrib)      _render_mode;
   CPT(RescaleNormalAttrib)   _rescale_normal;
@@ -95,9 +97,8 @@ class EXPCL_PANDA_PGRAPH AttribSlots
 
  public:
   // Each "array" reference requires a switch and a DCAST, so it's not overly fast.
-  enum { slot_count=24 };
+  enum { slot_count=26 };
   const RenderAttrib *get_slot(int n) const;
-  void set_slot(int n, const RenderAttrib *attrib);
 
  private:
   static AttribSlots _defvals;

+ 3 - 0
panda/src/pgraph/config_pgraph.cxx

@@ -53,6 +53,7 @@
 #include "lensNode.h"
 #include "light.h"
 #include "lightAttrib.h"
+#include "lightRampAttrib.h"
 #include "lightLensNode.h"
 #include "lightNode.h"
 #include "loader.h"
@@ -403,6 +404,7 @@ init_libpgraph() {
   LensNode::init_type();
   Light::init_type();
   LightAttrib::init_type();
+  LightRampAttrib::init_type();
   LightLensNode::init_type();
   LightNode::init_type();
   Loader::init_type();
@@ -482,6 +484,7 @@ init_libpgraph() {
   GeomNode::register_with_read_factory();
   LensNode::register_with_read_factory();
   LightAttrib::register_with_read_factory();
+  LightRampAttrib::register_with_read_factory();
   LODNode::register_with_read_factory();
   MaterialAttrib::register_with_read_factory();
   ModelNode::register_with_read_factory();

+ 1 - 0
panda/src/pgraph/pgraph_composite3.cxx

@@ -2,6 +2,7 @@
 #include "lensNode.cxx"
 #include "light.cxx"
 #include "lightAttrib.cxx"
+#include "lightRampAttrib.cxx"
 #include "lightLensNode.cxx"
 #include "lightNode.cxx"
 #include "loader.cxx"

+ 130 - 58
panda/src/pgraph/shaderGenerator.cxx

@@ -15,41 +15,6 @@
 // [email protected] .
 //
 ////////////////////////////////////////////////////////////////////
-//
-// Lighting calculations. These can be done either in tangent space
-// or model space.  Doing them in tangent space is necessary for
-// normal mapping.  However, it is only possible if tangents have
-// been computed.  If not, then model space is the only option.
-// The parameters needed for lighting are:
-//
-// Model Space:
-//
-//   vshader:
-//       model-space normal - varying
-//       model-space vertex position - varying
-//   fshader:
-//       model-space normal - varying
-//       model-space vertex position - varying
-//       model-space light position (spot or point) - uniform
-//       model-space light vector (directional) - uniform
-//       model-space eye position - uniform
-//
-// Tangent Space:
-//
-//   vshader:
-//       model-space normal - varying
-//       model-space tangent - varying
-//       model-space binormal - varying
-//       model-space light position (spot or point) - uniform
-//       model-space light vector (directional) - uniform
-//       model-space eye position - uniform
-//   fshader:
-//       model-space vertex position - varying
-//       tangent-space light vector, one per light - varying
-//       tangent-space eye vector - varying
-//       model-space light position (spot) - uniform
-//
-/////////////////////////////////////////////////////////////////////
 
 
 #include "renderState.h"
@@ -244,7 +209,7 @@ analyze_renderstate(const RenderState *rs) {
     }
   }
   
-  // Determine whether model-space or tangent-space lighting is recommended.
+  // Determine whether lighting is needed.
 
   if (_attribs._light->get_num_on_lights() > 0) {
     _lighting = true;
@@ -295,9 +260,36 @@ analyze_renderstate(const RenderState *rs) {
       if ((s[0]!=0.0)||(s[1]!=0.0)||(s[2]!=0.0)) {
         _have_specular = true;
       }
+    } else if (_map_index_gloss >= 0) {
+      _have_specular = true;
     }
   }
   
+  // Decide whether to separate ambient and diffuse calculations.
+
+  if (_have_ambient && _have_diffuse) {
+    if (_material->has_ambient()) {
+      if (_material->has_diffuse()) {
+        _separate_ambient_diffuse = _material->get_ambient() != _material->get_diffuse();
+      } else {
+        _separate_ambient_diffuse = true;
+      }
+    } else {
+      if (_material->has_diffuse()) {
+        _separate_ambient_diffuse = true;
+      } else {
+        _separate_ambient_diffuse = false;
+      }
+    }
+  }
+
+  if (_attribs._light_ramp->get_mode() != LightRampAttrib::LRT_identity) {
+    if (_separate_ambient_diffuse) {
+      pgraph_cat.error() << "Light Ramp incompatible with separate ambient/diffuse\n";
+      _separate_ambient_diffuse = false;
+    }
+  }
+
   // Does the shader need material properties as input?
   
   _need_material_props = 
@@ -325,6 +317,7 @@ clear_analysis() {
   _have_diffuse = false;
   _have_emission = false;
   _have_specular = false;
+  _separate_ambient_diffuse = false;
   _map_index_normal = -1;
   _map_index_height = -1;
   _map_index_glow = -1;
@@ -381,18 +374,22 @@ create_shader_attrib(const string &txt) {
 //               - vertex colors
 //               - lighting
 //               - normal maps
+//               - gloss maps
 //               - materials, but not updates to materials
 //               - modulated 2D textures
+//               - texture stage modes: modulate, decal, add
+//               - light ramps (for cartoon shading)
 //
 //               Not yet supported:
 //               - 3D textures
 //               - cube textures
-//               - texture stage modes: decal, blend, replace, add, etc.
+//               - texture stage modes: replace, blend
 //               - color scale attrib
 //               - texgen
 //               - texmatrix
-//               - gloss maps
-//               - glow maps
+//               - glow maps (not yet sure what these should do)
+//               - other TextureStage::Modes
+//               - cartoon thresholding and other special effects
 //
 ////////////////////////////////////////////////////////////////////
 CPT(RenderAttrib) ShaderGenerator::
@@ -527,16 +524,6 @@ synthesize_shader(const RenderState *rs) {
   }
   
   if (_lighting) {
-    text << "\t // Begin model-space light calculations\n";
-    if (_have_ambient) {
-      text << "\t float4 tot_ambient = float4(0,0,0,0);\n";
-    }
-    if (_have_diffuse) {
-      text << "\t float4 tot_diffuse = float4(0,0,0,0);\n";
-    }
-    if (_have_specular) {
-      text << "\t float4 tot_specular = float4(0,0,0,0);\n";
-    }
     if (_map_index_normal) {
       text << "\t // Translate tangent-space normal in map to model-space.\n";
       text << "\t float3 tsnormal = ((float3)tex" << _map_index_normal << " * 2) - 1;\n";
@@ -545,14 +532,40 @@ synthesize_shader(const RenderState *rs) {
       text << "\t l_normal+= l_binormal * tsnormal.y;\n";
       text << "\t l_normal = normalize(l_normal);\n";
     } else {
+      text << "\t // Correct the surface normal for interpolation effects\n";
       text << "\t l_normal = normalize(l_normal);\n";
     }
+    text << "\t // Begin model-space light calculations\n";
     text << "\t float ldist,lattenv,langle;\n";
     text << "\t float4 lcolor,lspec,lvec,lpoint,latten,ldir,leye,lhalf;\n";
+    if (_separate_ambient_diffuse) {
+      if (_have_ambient) {
+        text << "\t float4 tot_ambient = float4(0,0,0,0);\n";
+      }
+      if (_have_diffuse) {
+        text << "\t float4 tot_diffuse = float4(0,0,0,0);\n";
+      }
+    } else {
+      if (_have_ambient || _have_diffuse) {
+        text << "\t float4 tot_diffuse = float4(0,0,0,0);\n";
+      }
+    }
+    if (_have_specular) {
+      text << "\t float4 tot_specular = float4(0,0,0,0);\n";
+      if (_material->has_specular()) {
+        text << "\t float shininess = attr_material[3].w;\n";
+      } else {
+        text << "\t float shininess = 50; // no shininess specified, using default\n";
+      }
+    }
     for (int i=0; i<(int)_alights.size(); i++) {
       text << "\t // Ambient Light " << i << "\n";
       text << "\t lcolor = alight_alight" << i << ";\n";
-      text << "\t tot_ambient += lcolor;\n";
+      if (_separate_ambient_diffuse) {
+        text << "\t tot_ambient += lcolor;\n";
+      } else {
+        text << "\t tot_diffuse += lcolor;\n";
+      }
     }
     for (int i=0; i<(int)_dlights.size(); i++) {
       text << "\t // Directional Light " << i << "\n";
@@ -567,7 +580,7 @@ synthesize_shader(const RenderState *rs) {
         } else {
           text << "\t lhalf = dlight_dlight" << i << "_rel_model[3];\n";
         }
-        text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), attr_material[3].w);\n";
+        text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), shininess);\n";
         text << "\t tot_specular += lspec;\n";
       }
     }
@@ -590,7 +603,7 @@ synthesize_shader(const RenderState *rs) {
           text << "\t lhalf = normalize(lvec - row1_view_to_model);\n";
         }
         text << "\t lspec *= lattenv;\n";
-        text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), attr_material[3].w);\n";
+        text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), shininess);\n";
         text << "\t tot_specular += lspec;\n";
       }
     }
@@ -617,18 +630,47 @@ synthesize_shader(const RenderState *rs) {
           text << "\t lhalf = normalize(lvec - row1_view_to_model);\n";
         }
         text << "\t lspec *= lattenv;\n";
-        text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), attr_material[3].w);\n";
+        text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), shininess);\n";
         text << "\t tot_specular += lspec;\n";
       }
     }
+    switch (_attribs._light_ramp->get_mode()) {
+    case LightRampAttrib::LRT_identity:
+      break;
+    case LightRampAttrib::LRT_single_threshold:
+      {
+        float t = _attribs._light_ramp->get_threshold(0);
+        float l0 = _attribs._light_ramp->get_level(0);
+        float l1 = _attribs._light_ramp->get_level(1);
+        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_out = (lr_in < " << t << ") ? " << l0 << ":" << l1 << ";\n";
+        text << "\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n";
+        break;
+      }
+    case LightRampAttrib::LRT_double_threshold:
+      {
+        float t0 = _attribs._light_ramp->get_threshold(0);
+        float t1 = _attribs._light_ramp->get_threshold(1);
+        float l0 = _attribs._light_ramp->get_level(0);
+        float l1 = _attribs._light_ramp->get_level(1);
+        float l2 = _attribs._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 model-space light summation\n";
-
     if (_have_emission) {
       text << "\t o_color = attr_material[2];\n";
     } else {
       text << "\t o_color = float4(0,0,0,0);\n";
     }
-    if (_have_ambient) {
+    if ((_have_ambient)&&(_separate_ambient_diffuse)) {
       if (_material->has_ambient()) {
         text << "\t o_color += tot_ambient * attr_material[0];\n";
       } else if (_vertex_colors) {
@@ -669,14 +711,44 @@ synthesize_shader(const RenderState *rs) {
   }
   for (int i=0; i<_num_textures; i++) {
     TextureStage *stage = _attribs._texture->get_on_stage(i);
-    if ((stage->get_mode() != TextureStage::M_normal)&&
-        (stage->get_mode() != TextureStage::M_normal_height)) {
+    switch (stage->get_mode()) {
+    case TextureStage::M_modulate:
+    case TextureStage::M_modulate_glow:
+    case TextureStage::M_modulate_gloss:
       text << "\t o_color *= tex" << i << ";\n";
+      break;
+    case TextureStage::M_decal:
+      text << "\t o_color.rgb = lerp(o_color, tex" << i << ", tex" << i << ".a).rgb;\n";
+      break;
+    case TextureStage::M_blend:
+      pgraph_cat.error() << "TextureStage::Mode BLEND not yet supported in per-pixel mode.\n";
+      break;
+    case TextureStage::M_replace:
+      pgraph_cat.error() << "TextureStage::Mode REPLACE not yet supported in per-pixel mode.\n";
+      break;
+    case TextureStage::M_add:
+      text << "\t o_color.rbg = o_color.rgb + tex" << i << ".rgb;\n";
+      text << "\t o_color.a   = o_color.a * tex" << i << ".a;\n";
+      break;
+    case TextureStage::M_combine:
+      pgraph_cat.error() << "TextureStage::Mode COMBINE not yet supported in per-pixel mode.\n";
+      break;
+    case TextureStage::M_blend_color_scale:
+      pgraph_cat.error() << "TextureStage::Mode BLEND_COLOR_SCALE not yet supported in per-pixel mode.\n";
+      break;
+    default:
+      break;
     }
   }
   if (_lighting) {
     if (_have_specular) {
-      text << "\t o_color += tot_specular;\n";
+      if (_material->has_specular()) {
+        text << "\t tot_specular *= attr_material[3];\n";
+      }
+      if (_map_index_gloss >= 0) {
+        text << "\t tot_specular *= tex" << _map_index_gloss << ".a;\n";
+      }
+      text << "\t o_color.rgb = o_color.rgb + tot_specular.rgb;\n";
     }
   }
   text << "}\n";

+ 3 - 1
panda/src/pgraph/shaderGenerator.h

@@ -110,7 +110,9 @@ protected:
   bool _have_diffuse;
   bool _have_emission;
   bool _have_specular;
-
+  
+  bool _separate_ambient_diffuse;
+  
   int _map_index_normal;
   int _map_index_height;
   int _map_index_glow;