Browse Source

Add support for more TexGen modes

rdb 16 years ago
parent
commit
b83e30b645
2 changed files with 109 additions and 63 deletions
  1. 105 62
      panda/src/pgraphnodes/shaderGenerator.cxx
  2. 4 1
      panda/src/pgraphnodes/shaderGenerator.h

+ 105 - 62
panda/src/pgraphnodes/shaderGenerator.cxx

@@ -182,6 +182,10 @@ analyze_renderstate(const RenderState *rs) {
   _out_aux_normal = (outputs & AuxBitplaneAttrib::ABO_aux_normal) ? true:false;
   _out_aux_glow = (outputs & AuxBitplaneAttrib::ABO_aux_glow) ? true:false;
   _out_aux_any = (_out_aux_normal || _out_aux_glow);
+  
+  if (_out_aux_normal) {
+    _need_eye_normal = true;
+  }
 
   // Count number of textures.
 
@@ -257,8 +261,19 @@ analyze_renderstate(const RenderState *rs) {
       _map_height_in_alpha = true;
     }
     if (tex_gen->has_stage(stage)) {
-      if (tex_gen->get_mode(stage) == TexGenAttrib::M_world_position) {
-        _need_worldspace_pos = true;
+      switch (tex_gen->get_mode(stage)) {
+        case TexGenAttrib::M_world_position:
+          _need_world_position = true;
+          break;
+        case TexGenAttrib::M_world_normal:
+          _need_world_normal = true;
+          break;
+        case TexGenAttrib::M_eye_position:
+          _need_eye_position = true;
+          break;
+        case TexGenAttrib::M_eye_normal:
+          _need_eye_normal = true;
+          break;
       }
     }
   }
@@ -267,6 +282,8 @@ analyze_renderstate(const RenderState *rs) {
 
   if (la->get_num_on_lights() > 0) {
     _lighting = true;
+    _need_eye_position = true;
+    _need_eye_normal = true;
   }
 
   // Find the material.
@@ -363,7 +380,7 @@ analyze_renderstate(const RenderState *rs) {
   const ClipPlaneAttrib *clip_plane = DCAST(ClipPlaneAttrib, rs->get_attrib_def(ClipPlaneAttrib::get_class_slot()));
   _num_clip_planes = clip_plane->get_num_on_planes();
   if (_num_clip_planes > 0) {
-    _need_worldspace_pos = true;
+    _need_world_position = true;
   }
 
   // Check for unimplemented features and issue warnings.
@@ -408,8 +425,11 @@ clear_analysis() {
   _out_aux_glow     = false;
   _out_aux_any      = false;
   _material = (Material*)NULL;
-  _need_worldspace_pos = false;
   _need_material_props = false;
+  _need_world_position = false;
+  _need_world_normal = false;
+  _need_eye_position = false;
+  _need_eye_normal = false;
   _alights.clear();
   _dlights.clear();
   _plights.clear();
@@ -541,9 +561,7 @@ synthesize_shader(const RenderState *rs) {
 
   // These variables will hold the results of register allocation.
 
-  char *pos_freg = 0;
   char *normal_vreg = 0;
-  char *normal_freg = 0;
   char *ntangent_vreg = 0;
   char *ntangent_freg = 0;
   char *nbinormal_vreg = 0;
@@ -553,6 +571,10 @@ synthesize_shader(const RenderState *rs) {
   pvector<char *> texcoord_vreg;
   pvector<char *> texcoord_freg;
   pvector<char *> tslightvec_freg;
+  char *world_position_freg = 0;
+  char *world_normal_freg = 0;
+  char *eye_position_freg = 0;
+  char *eye_normal_freg = 0;
 
   if (_vertex_colors) {
     _vcregs_used = 1;
@@ -580,10 +602,31 @@ synthesize_shader(const RenderState *rs) {
     text << "\t in float4 vtx_color : COLOR,\n";
     text << "\t out float4 l_color : COLOR,\n";
   }
-  if (_need_worldspace_pos > 0) {
-    text << "\t out float4 l_worldpos,\n";
+  if (_need_world_position || _need_world_normal) {
     text << "\t uniform float4x4 trans_model_to_world,\n";
   }
+  if (_need_world_position) {
+    world_position_freg = alloc_freg();
+    text << "\t out float4 l_world_position : " << world_position_freg << ",\n";
+  }
+  if (_need_world_normal) {
+    world_normal_freg = alloc_freg();
+    text << "\t out float4 l_world_normal : " << world_normal_freg << ",\n";
+  }
+  if (_need_eye_position) {
+    text << "\t uniform float4x4 trans_model_to_view,\n";
+    eye_position_freg = alloc_freg();
+    text << "\t out float4 l_eye_position : " << eye_position_freg << ",\n";
+  }
+  if (_need_eye_normal) {
+    eye_normal_freg = alloc_freg();
+    text << "\t uniform float4x4 tpose_view_to_model,\n";
+    text << "\t out float4 l_eye_normal : " << eye_normal_freg << ",\n";
+  }
+  if (_map_index_height >= 0 || _need_world_normal || _need_eye_normal) {
+    normal_vreg = alloc_vreg();
+    text << "\t in float4 vtx_normal : " << normal_vreg << ",\n";
+  }
   if (_map_index_height >= 0) {
     htangent_vreg = alloc_vreg();
     hbinormal_vreg = alloc_vreg();
@@ -596,17 +639,7 @@ synthesize_shader(const RenderState *rs) {
     text << "\t uniform float4 mspos_view,\n";
     text << "\t out float3 l_eyevec,\n";
   }
-  if (_map_index_height >= 0 || _lighting) {
-    normal_vreg = alloc_vreg();
-    text << "\t in float4 vtx_normal : " << normal_vreg << ",\n";
-  }
   if (_lighting) {
-    pos_freg = alloc_freg();
-    normal_freg = alloc_freg();
-    text << "\t uniform float4x4 trans_model_to_view,\n";
-    text << "\t uniform float4x4 tpose_view_to_model,\n";
-    text << "\t out float4 l_normal : " << normal_freg << ",\n";
-    text << "\t out float4 l_pos : " << pos_freg << ",\n";
     if (_map_index_normal >= 0) {
       // 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) {
@@ -634,12 +667,6 @@ synthesize_shader(const RenderState *rs) {
         }
       }
     }
-  } else if (_out_aux_normal) {
-    normal_vreg = alloc_vreg();
-    normal_freg = alloc_freg();
-    text << "\t uniform float4x4 tpose_view_to_model,\n";
-    text << "\t in float4 vtx_normal : " << normal_vreg << ",\n";
-    text << "\t out float4 l_normal : " << normal_freg << ",\n";
   }
   text << "\t float4 vtx_position : POSITION,\n";
   text << "\t out float4 l_position : POSITION,\n";
@@ -647,8 +674,18 @@ synthesize_shader(const RenderState *rs) {
   text << ") {\n";
 
   text << "\t l_position = mul(mat_modelproj, vtx_position);\n";
-  if (_need_worldspace_pos) {
-    text << "\t l_worldpos = mul(trans_model_to_world, vtx_position);\n";
+  if (_need_world_position) {
+    text << "\t l_world_position = mul(trans_model_to_world, vtx_position);\n";
+  }
+  if (_need_world_normal) {
+    text << "\t l_world_normal = mul(trans_model_to_world, vtx_normal);\n";
+  }
+  if (_need_eye_position) {
+    text << "\t l_eye_position = mul(trans_model_to_view, vtx_position);\n";
+  }
+  if (_need_eye_normal) {
+    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))) {
@@ -658,13 +695,6 @@ synthesize_shader(const RenderState *rs) {
   if (_vertex_colors) {
     text << "\t l_color = vtx_color;\n";
   }
-  if (_lighting) {
-    text << "\t l_pos = mul(trans_model_to_view, vtx_position);\n";
-  }
-  if (_lighting || _out_aux_normal) {
-    text << "\t l_normal.xyz = mul((float3x3)tpose_view_to_model, vtx_normal.xyz);\n";
-    text << "\t l_normal.w = 0;\n";
-  }
   if (_lighting && (_map_index_normal >= 0)) {
     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";
@@ -696,8 +726,17 @@ synthesize_shader(const RenderState *rs) {
   text << "}\n\n";
 
   text << "void fshader(\n";
-  if (_need_worldspace_pos) {
-    text << "\t in float4 l_worldpos,\n";
+  if (_need_world_position) {
+    text << "\t in float4 l_world_position : " << world_position_freg << ",\n";
+  }
+  if (_need_world_normal) {
+    text << "\t in float4 l_world_normal : " << world_normal_freg << ",\n";
+  }
+  if (_need_eye_position) { 
+    text << "\t in float4 l_eye_position : " << eye_position_freg << ",\n";
+  }
+  if (_need_eye_normal) {
+    text << "\t in float4 l_eye_normal : " << eye_normal_freg << ",\n";
   }
   const TexMatrixAttrib *tex_matrix = DCAST(TexMatrixAttrib, rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
   for (int i=0; i<_num_textures; i++) {
@@ -710,18 +749,11 @@ synthesize_shader(const RenderState *rs) {
       text << "\t uniform float4x4 texmat_" << i << ",\n";
     }
   }
-  if (_lighting || _out_aux_normal) {
-    text << "\t in float3 l_normal : " << normal_freg << ",\n";
-  }
   if (_lighting && (_map_index_normal >= 0)) {
     text << "\t in float3 l_tangent : " << ntangent_freg << ",\n";
     text << "\t in float3 l_binormal : " << nbinormal_freg << ",\n";
   }
   if (_lighting) {
-    text << "\t in float4 l_pos : " << pos_freg << ",\n";
-    if (_shadows) {
-      text << "\t in float4 l_position : " << alloc_freg() << ",\n";
-    }
     for (int i=0; i<(int)_alights.size(); i++) {
       text << "\t uniform float4 alight_alight" << i << ",\n";
     }
@@ -781,8 +813,8 @@ synthesize_shader(const RenderState *rs) {
   text << ") {\n";
   // Clipping first!
   for (int i=0; i<_num_clip_planes; ++i) {
-    text << "\t if (l_worldpos.x * clipplane_" << i << ".x + l_worldpos.y ";
-    text << "* clipplane_" << i << ".y + l_worldpos.z * clipplane_" << i << ".z + clipplane_" << i << ".w <= 0) {\n";
+    text << "\t if (l_world_position.x * clipplane_" << i << ".x + l_world_position.y ";
+    text << "* clipplane_" << i << ".y + l_world_position.z * clipplane_" << i << ".z + clipplane_" << i << ".w <= 0) {\n";
     text << "\t discard;\n";
     text << "\t }\n";
   }
@@ -796,10 +828,21 @@ 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_worldpos;\n";
+          text << "\t float4 l_texcoord" << i << " = l_world_position;\n";
+          break;
+        case TexGenAttrib::M_world_normal:
+          text << "\t float4 l_texcoord" << i << " = l_world_normal;\n";
+          break;
+        case TexGenAttrib::M_eye_position:
+          text << "\t float4 l_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";
           break;
         default:
           pgraph_cat.error() << "Unsupported TexGenAttrib mode\n";
+          text << "\t float4 l_texcoord" << i << " = float4(0, 0, 0, 0);\n";
       }
     }
     if (tex_matrix != NULL && tex_matrix->has_stage(stage)) {
@@ -833,18 +876,18 @@ synthesize_shader(const RenderState *rs) {
     if (_map_index_normal >= 0) {
       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_normal = l_normal * tsnormal.z;\n";
-      text << "\t l_normal+= l_tangent * tsnormal.x;\n";
-      text << "\t l_normal+= l_binormal * tsnormal.y;\n";
-      text << "\t l_normal = normalize(l_normal);\n";
+      text << "\t l_eye_normal = l_eye_normal * tsnormal.z;\n";
+      text << "\t l_eye_normal+= l_tangent * tsnormal.x;\n";
+      text << "\t l_eye_normal+= l_binormal * tsnormal.y;\n";
+      text << "\t l_eye_normal = normalize(l_eye_normal);\n";
     } else {
       text << "\t // Correct the surface normal for interpolation effects\n";
-      text << "\t l_normal = normalize(l_normal);\n";
+      text << "\t l_eye_normal.xyz = normalize(l_eye_normal.xyz);\n";
     }
   }
   if (_out_aux_normal) {
     text << "\t // Output the camera-space surface normal\n";
-    text << "\t o_aux.rgb = (l_normal.rgb*0.5) + float3(0.5,0.5,0.5);\n";
+    text << "\t o_aux.rgb = (l_eye_normal.xyz*0.5) + float3(0.5,0.5,0.5);\n";
   }
   if (_lighting) {
     text << "\t // Begin view-space light calculations\n";
@@ -887,7 +930,7 @@ synthesize_shader(const RenderState *rs) {
       text << "\t lcolor = dlight_dlight" << i << "_rel_view[0];\n";
       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_normal, lvec.xyz));\n";
+      text << "\t lcolor *= saturate(dot(l_eye_normal, lvec.xyz));\n";
       if (_shadows && _dlights[i]->_shadow_caster) {
         if (_use_shadow_filter) {
           text << "\t lshad = shadow2DProj(k_dlighttex" << i << ", l_dlightcoord" << i << ").r;\n";
@@ -902,11 +945,11 @@ synthesize_shader(const RenderState *rs) {
       }
       if (_have_specular) {
         if (_material->get_local()) {
-          text << "\t lhalf  = normalize(lvec - normalize(l_pos));\n";
+          text << "\t lhalf  = normalize(lvec - normalize(l_eye_position));\n";
         } else {
           text << "\t lhalf = dlight_dlight" << i << "_rel_view[3];\n";
         }
-        text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), shininess);\n";
+        text << "\t lspec *= pow(saturate(dot(l_eye_normal, lhalf.xyz)), shininess);\n";
         text << "\t tot_specular += lspec;\n";
       }
     }
@@ -916,22 +959,22 @@ synthesize_shader(const RenderState *rs) {
       text << "\t lspec  = plight_plight" << i << "_rel_view[1];\n";
       text << "\t lpoint = plight_plight" << i << "_rel_view[2];\n";
       text << "\t latten = plight_plight" << i << "_rel_view[3];\n";
-      text << "\t lvec   = lpoint - l_pos;\n";
+      text << "\t lvec   = lpoint - l_eye_position;\n";
       text << "\t ldist = length(float3(lvec));\n";
       text << "\t lvec /= ldist;\n";
       text << "\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n";
-      text << "\t lcolor *= lattenv * saturate(dot(l_normal, lvec.xyz));\n";
+      text << "\t lcolor *= lattenv * saturate(dot(l_eye_normal, lvec.xyz));\n";
       if (_have_diffuse) {
         text << "\t tot_diffuse += lcolor;\n";
       }
       if (_have_specular) {
         if (_material->get_local()) {
-          text << "\t lhalf  = normalize(lvec - normalize(l_pos));\n";
+          text << "\t lhalf  = normalize(lvec - normalize(l_eye_position));\n";
         } else {
           text << "\t lhalf = normalize(lvec - float4(0,1,0,0));\n";
         }
         text << "\t lspec *= lattenv;\n";
-        text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), shininess);\n";
+        text << "\t lspec *= pow(saturate(dot(l_eye_normal, lhalf.xyz)), shininess);\n";
         text << "\t tot_specular += lspec;\n";
       }
     }
@@ -942,14 +985,14 @@ synthesize_shader(const RenderState *rs) {
       text << "\t lpoint = slight_slight" << i << "_rel_view[2];\n";
       text << "\t ldir   = slight_slight" << i << "_rel_view[3];\n";
       text << "\t latten = satten_slight" << i << ";\n";
-      text << "\t lvec   = lpoint - l_pos;\n";
+      text << "\t lvec   = lpoint - l_eye_position;\n";
       text << "\t ldist  = length(float3(lvec));\n";
       text << "\t lvec /= ldist;\n";
       text << "\t langle = saturate(dot(ldir.xyz, lvec.xyz));\n";
       text << "\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n";
       text << "\t lattenv *= pow(langle, latten.w);\n";
       text << "\t if (langle < ldir.w) lattenv = 0;\n";
-      text << "\t lcolor *= lattenv * saturate(dot(l_normal, lvec.xyz));\n";
+      text << "\t lcolor *= lattenv * saturate(dot(l_eye_normal, lvec.xyz));\n";
       if (_shadows && _slights[i]->_shadow_caster) {
         if (_use_shadow_filter) {
           text << "\t lshad = shadow2DProj(k_slighttex" << i << ", l_slightcoord" << i << ").r;\n";
@@ -965,12 +1008,12 @@ synthesize_shader(const RenderState *rs) {
       }
       if (_have_specular) {
         if (_material->get_local()) {
-          text << "\t lhalf  = normalize(lvec - normalize(l_pos));\n";
+          text << "\t lhalf  = normalize(lvec - normalize(l_eye_position));\n";
         } else {
           text << "\t lhalf = normalize(lvec - float4(0,1,0,0));\n";
         }
         text << "\t lspec *= lattenv;\n";
-        text << "\t lspec *= pow(saturate(dot(l_normal, lhalf.xyz)), shininess);\n";
+        text << "\t lspec *= pow(saturate(dot(l_eye_normal, lhalf.xyz)), shininess);\n";
         text << "\t tot_specular += lspec;\n";
       }
     }

+ 4 - 1
panda/src/pgraphnodes/shaderGenerator.h

@@ -135,8 +135,11 @@ protected:
   int _num_clip_planes;
   bool _use_shadow_filter;
 
-  bool _need_worldspace_pos;
   bool _need_material_props;
+  bool _need_world_position;
+  bool _need_world_normal;
+  bool _need_eye_position;
+  bool _need_eye_normal;
 
   void analyze_renderstate(const RenderState *rs);
   void clear_analysis();