Browse Source

Added support for shadow maps + shaders

Josh Yelon 20 years ago
parent
commit
0400248b37

+ 16 - 4
direct/src/showbase/ShowBase.py

@@ -64,7 +64,7 @@ class ShowBase(DirectObject.DirectObject):
         self.sfxActive = self.config.GetBool('audio-sfx-active', 1)
         self.sfxActive = self.config.GetBool('audio-sfx-active', 1)
         self.musicActive = self.config.GetBool('audio-music-active', 1)
         self.musicActive = self.config.GetBool('audio-music-active', 1)
         self.wantFog = self.config.GetBool('want-fog', 1)
         self.wantFog = self.config.GetBool('want-fog', 1)
-        self.wantRender2dp = self.config.GetBool('want-render2dp', 0)
+        self.wantRender2dp = self.config.GetBool('want-render2dp', 1)
 
 
         self.screenshotExtension = self.config.GetString('screenshot-extension', 'jpg')
         self.screenshotExtension = self.config.GetString('screenshot-extension', 'jpg')
         self.musicManager = None
         self.musicManager = None
@@ -117,12 +117,14 @@ class ShowBase(DirectObject.DirectObject):
         self.drive = None
         self.drive = None
         self.trackball = None
         self.trackball = None
         self.cam = None
         self.cam = None
-        self.camList = []
-        self.camNode = None
-        self.camLens = None
+        self.cam2d = None
+        self.cam2dp = None
         self.camera = None
         self.camera = None
         self.camera2d = None
         self.camera2d = None
         self.camera2dp = None
         self.camera2dp = None
+        self.camList = []
+        self.camNode = None
+        self.camLens = None
         self.camFrustumVis = None
         self.camFrustumVis = None
 
 
         # This is used for syncing multiple PCs in a distributed cluster
         # This is used for syncing multiple PCs in a distributed cluster
@@ -458,6 +460,10 @@ class ShowBase(DirectObject.DirectObject):
                 # preserve it for reopening the window.
                 # preserve it for reopening the window.
                 if cam == self.cam:
                 if cam == self.cam:
                     self.cam = None
                     self.cam = None
+                if cam == self.cam2d:
+                    self.cam2d = None
+                if cam == self.cam2dp:
+                    self.cam2dp = None
                 cam.removeNode()
                 cam.removeNode()
 
 
         # Now we can actually close the window.
         # Now we can actually close the window.
@@ -813,6 +819,9 @@ class ShowBase(DirectObject.DirectObject):
         camera2d = self.camera2d.attachNewNode(cam2dNode)
         camera2d = self.camera2d.attachNewNode(cam2dNode)
         dr.setCamera(camera2d)
         dr.setCamera(camera2d)
 
 
+        if self.cam2d == None:
+            self.cam2d = camera2d
+
         return camera2d
         return camera2d
 
 
     def makeCamera2dp(self, win, sort = 20,
     def makeCamera2dp(self, win, sort = 20,
@@ -847,6 +856,9 @@ class ShowBase(DirectObject.DirectObject):
         camera2dp = self.camera2dp.attachNewNode(cam2dNode)
         camera2dp = self.camera2dp.attachNewNode(cam2dNode)
         dr.setCamera(camera2dp)
         dr.setCamera(camera2dp)
 
 
+        if self.cam2dp == None:
+            self.cam2dp = camera2dp
+
         return camera2dp
         return camera2dp
 
 
 
 

+ 2 - 2
panda/src/display/graphicsOutput.cxx

@@ -520,7 +520,7 @@ create_texture_card_vdata(int x, int y)
   float xhi = (x * 1.0f) / xru;
   float xhi = (x * 1.0f) / xru;
   float yhi = (y * 1.0f) / yru;
   float yhi = (y * 1.0f) / yru;
   
   
-  CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3n3cpt2();
+  CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3n3t2();
   
   
   PT(GeomVertexData) vdata = new GeomVertexData
   PT(GeomVertexData) vdata = new GeomVertexData
     ("card", format, Geom::UH_static);
     ("card", format, Geom::UH_static);
@@ -528,7 +528,7 @@ create_texture_card_vdata(int x, int y)
   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
   GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
   GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
   GeomVertexWriter normal(vdata, InternalName::get_normal());
   GeomVertexWriter normal(vdata, InternalName::get_normal());
-    
+  
   vertex.add_data3f(Vertexf::rfu(-1.0f, 0.0f,  1.0f));
   vertex.add_data3f(Vertexf::rfu(-1.0f, 0.0f,  1.0f));
   vertex.add_data3f(Vertexf::rfu(-1.0f, 0.0f, -1.0f));
   vertex.add_data3f(Vertexf::rfu(-1.0f, 0.0f, -1.0f));
   vertex.add_data3f(Vertexf::rfu( 1.0f, 0.0f,  1.0f));
   vertex.add_data3f(Vertexf::rfu( 1.0f, 0.0f,  1.0f));

+ 22 - 0
panda/src/display/graphicsStateGuardian.I

@@ -470,6 +470,28 @@ get_supports_render_texture() const {
   return _supports_render_texture;
   return _supports_render_texture;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::get_supports_depth_texture
+//       Access: Published
+//  Description: Returns true if this particular GSG supports
+//               textures whose format is F_depth_component.
+////////////////////////////////////////////////////////////////////
+INLINE bool GraphicsStateGuardian::
+get_supports_depth_texture() const {
+  return _supports_depth_texture;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::get_supports_shadow_filter
+//       Access: Published
+//  Description: Returns true if this particular GSG supports
+//               the filter mode FT_shadow for depth textures.
+////////////////////////////////////////////////////////////////////
+INLINE bool GraphicsStateGuardian::
+get_supports_shadow_filter() const {
+  return _supports_shadow_filter;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_color_scale_via_lighting
 //     Function: GraphicsStateGuardian::get_color_scale_via_lighting
 //       Access: Published
 //       Access: Published

+ 2 - 1
panda/src/display/graphicsStateGuardian.cxx

@@ -145,7 +145,8 @@ GraphicsStateGuardian(const FrameBufferProperties &properties,
   _supports_multisample = false;
   _supports_multisample = false;
   _supports_generate_mipmap = false;
   _supports_generate_mipmap = false;
   _supports_render_texture = false;
   _supports_render_texture = false;
-
+  _supports_depth_texture = false;
+  _supports_shadow_filter = false;
   _supported_geom_rendering = 0;
   _supported_geom_rendering = 0;
 
 
   // If this is true, then we can apply a color and/or color scale by
   // If this is true, then we can apply a color and/or color scale by

+ 6 - 2
panda/src/display/graphicsStateGuardian.h

@@ -109,11 +109,13 @@ PUBLISHED:
   virtual bool get_supports_multisample() const;
   virtual bool get_supports_multisample() const;
   INLINE bool get_supports_generate_mipmap() const;
   INLINE bool get_supports_generate_mipmap() const;
   INLINE bool get_supports_render_texture() const;
   INLINE bool get_supports_render_texture() const;
+  INLINE bool get_supports_depth_texture() const;
+  INLINE bool get_supports_shadow_filter() const;
 
 
   virtual int get_supported_geom_rendering() const;
   virtual int get_supported_geom_rendering() const;
 
 
   INLINE bool get_color_scale_via_lighting() const;
   INLINE bool get_color_scale_via_lighting() const;
-
+  
   void set_coordinate_system(CoordinateSystem cs);
   void set_coordinate_system(CoordinateSystem cs);
   INLINE CoordinateSystem get_coordinate_system() const;
   INLINE CoordinateSystem get_coordinate_system() const;
   virtual CoordinateSystem get_internal_coordinate_system() const;
   virtual CoordinateSystem get_internal_coordinate_system() const;
@@ -355,9 +357,11 @@ protected:
   bool _supports_multisample;
   bool _supports_multisample;
   bool _supports_generate_mipmap;
   bool _supports_generate_mipmap;
   bool _supports_render_texture;
   bool _supports_render_texture;
+  bool _supports_depth_texture;
+  bool _supports_shadow_filter;
   int _supported_geom_rendering;
   int _supported_geom_rendering;
   bool _color_scale_via_lighting;
   bool _color_scale_via_lighting;
-
+  
 public:
 public:
   // Statistics
   // Statistics
   static PStatCollector _total_texusage_pcollector;
   static PStatCollector _total_texusage_pcollector;

+ 30 - 3
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -518,6 +518,16 @@ reset() {
     _glClientActiveTexture = null_glActiveTexture;
     _glClientActiveTexture = null_glActiveTexture;
   }
   }
 
 
+  if (has_extension("GL_ARB_depth_texture")) {
+    _supports_depth_texture = true;
+  }
+
+  if (_supports_depth_texture &&
+      has_extension("GL_ARB_shadow") &&
+      has_extension("GL_ARB_fragment_program_shadow")) {
+    _supports_shadow_filter = true;
+  }
+  
   _supports_texture_combine = 
   _supports_texture_combine = 
     has_extension("GL_ARB_texture_env_combine") || is_at_least_version(1, 3);
     has_extension("GL_ARB_texture_env_combine") || is_at_least_version(1, 3);
   _supports_texture_saved_result =
   _supports_texture_saved_result =
@@ -2041,7 +2051,7 @@ release_geom(GeomContext *gc) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 ShaderContext *CLP(GraphicsStateGuardian)::
 ShaderContext *CLP(GraphicsStateGuardian)::
 prepare_shader(ShaderExpansion *se) {
 prepare_shader(ShaderExpansion *se) {
-  CLP(ShaderContext) *result = new CLP(ShaderContext)(se);
+  CLP(ShaderContext) *result = new CLP(ShaderContext)(se, this);
   if (result->valid()) return result;
   if (result->valid()) return result;
   delete result;
   delete result;
   return NULL;
   return NULL;
@@ -2452,7 +2462,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
   } else {
   } else {
     nassertv(tex->get_texture_type() == Texture::TT_2d_texture);
     nassertv(tex->get_texture_type() == Texture::TT_2d_texture);
   }
   }
-
+  
   // Match framebuffer format if necessary.
   // Match framebuffer format if necessary.
   if (tex->get_match_framebuffer_format()) {
   if (tex->get_match_framebuffer_format()) {
     const FrameBufferProperties &properties = get_properties();
     const FrameBufferProperties &properties = get_properties();
@@ -3901,6 +3911,8 @@ get_texture_filter_type(Texture::FilterType ft, bool ignore_mipmaps) {
     case Texture::FT_nearest_mipmap_linear:
     case Texture::FT_nearest_mipmap_linear:
     case Texture::FT_linear_mipmap_linear:
     case Texture::FT_linear_mipmap_linear:
       return GL_LINEAR;
       return GL_LINEAR;
+    case Texture::FT_shadow:
+      return GL_LINEAR;
     case Texture::FT_invalid:
     case Texture::FT_invalid:
       break;
       break;
     }
     }
@@ -3919,6 +3931,8 @@ get_texture_filter_type(Texture::FilterType ft, bool ignore_mipmaps) {
       return GL_NEAREST_MIPMAP_LINEAR;
       return GL_NEAREST_MIPMAP_LINEAR;
     case Texture::FT_linear_mipmap_linear:
     case Texture::FT_linear_mipmap_linear:
       return GL_LINEAR_MIPMAP_LINEAR;
       return GL_LINEAR_MIPMAP_LINEAR;
+    case Texture::FT_shadow:
+      return GL_LINEAR;
     case Texture::FT_invalid:
     case Texture::FT_invalid:
       break;
       break;
     }
     }
@@ -5044,7 +5058,7 @@ update_standard_texture_bindings()
 
 
       GLP(MatrixMode)(GL_TEXTURE);
       GLP(MatrixMode)(GL_TEXTURE);
       if (_target._tex_matrix->has_stage(stage)) {
       if (_target._tex_matrix->has_stage(stage)) {
-        GLP(LoadMatrixf)(_state._tex_matrix->get_mat(stage).get_data());
+        GLP(LoadMatrixf)(_target._tex_matrix->get_mat(stage).get_data());
       } else {
       } else {
         GLP(LoadIdentity)();
         GLP(LoadIdentity)();
       }
       }
@@ -5444,6 +5458,19 @@ specify_texture(Texture *tex) {
   GLP(TexParameteri)(target, GL_TEXTURE_MAG_FILTER,
   GLP(TexParameteri)(target, GL_TEXTURE_MAG_FILTER,
                      get_texture_filter_type(magfilter, true));
                      get_texture_filter_type(magfilter, true));
 
 
+  if (_supports_shadow_filter) {
+    if (tex->get_format() == Texture::F_depth_component) {
+      if ((tex->get_magfilter() == Texture::FT_shadow) ||
+          (tex->get_minfilter() == Texture::FT_shadow)) {
+        GLP(TexParameteri)(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+        GLP(TexParameteri)(target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GEQUAL);
+      } else {
+        GLP(TexParameteri)(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+        GLP(TexParameteri)(target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+      }
+    }
+  }
+  
   report_my_gl_errors();
   report_my_gl_errors();
 }
 }
 
 

+ 75 - 3
panda/src/glstuff/glShaderContext_src.cxx

@@ -24,7 +24,7 @@ TypeHandle CLP(ShaderContext)::_type_handle;
 //  Description: xyz
 //  Description: xyz
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CLP(ShaderContext)::
 CLP(ShaderContext)::
-CLP(ShaderContext)(ShaderExpansion *s) : ShaderContext(s) {
+CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg) : ShaderContext(s) {
   string header;
   string header;
   s->parse_init();
   s->parse_init();
   s->parse_line(header, true, true);
   s->parse_line(header, true, true);
@@ -73,7 +73,7 @@ CLP(ShaderContext)(ShaderExpansion *s) : ShaderContext(s) {
     }
     }
     
     
     // Compile the program.
     // Compile the program.
-    try_cg_compile(s);
+    try_cg_compile(s, gsg);
     cerr << _cg_errors;
     cerr << _cg_errors;
     return;
     return;
   }
   }
@@ -155,7 +155,7 @@ parse_cg_profile(const string &id, bool vertex)
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 #ifdef HAVE_CGGL
 #ifdef HAVE_CGGL
 bool CLP(ShaderContext)::
 bool CLP(ShaderContext)::
-try_cg_compile(ShaderExpansion *s)
+try_cg_compile(ShaderExpansion *s, GSG *gsg)
 {
 {
   _cg_errors = "";
   _cg_errors = "";
   
   
@@ -176,6 +176,78 @@ try_cg_compile(ShaderExpansion *s)
     return false;
     return false;
   }
   }
   
   
+  // The following code is present to work around a bug in the Cg compiler.
+  // It does not generate correct code for shadow map lookups when using arbfp1.
+  // This is a particularly onerous limitation, given that arbfp1 is the only
+  // Cg target that works on radeons.  I suspect this is an intentional
+  // omission on nvidia's part.  The following code fetches the output listing,
+  // detects the error, repairs the code, and resumbits the repaired code to Cg.
+  if ((_cg_profile[1] == CG_PROFILE_ARBFP1) && (gsg->_supports_shadow_filter)) {
+    bool shadowunit[32];
+    bool anyshadow = false;
+    memset(shadowunit, 0, sizeof(shadowunit));
+    vector_string lines;
+    tokenize(cgGetProgramString(_cg_program[1], CG_COMPILED_PROGRAM), lines, "\n");
+    // figure out which texture units contain shadow maps.
+    for (int lineno=0; lineno<(int)lines.size(); lineno++) {
+      if (lines[lineno].compare(0,21,"#var sampler2DSHADOW ")) {
+        continue;
+      }
+      vector_string fields;
+      tokenize(lines[lineno], fields, ":");
+      if (fields.size()!=5) {
+        continue;
+      }
+      vector_string words;
+      tokenize(trim(fields[2]), words, " ");
+      if (words.size()!=2) {
+        continue;
+      }
+      int unit = atoi(words[1].c_str());
+      if ((unit < 0)||(unit >= 32)) {
+        continue;
+      }
+      anyshadow = true;
+      shadowunit[unit] = true;
+    }
+    // modify all TEX statements that use the relevant texture units.
+    if (anyshadow) {
+      for (int lineno=0; lineno<(int)lines.size(); lineno++) {
+        if (lines[lineno].compare(0,4,"TEX ")) {
+          continue;
+        }
+        vector_string fields;
+        tokenize(lines[lineno], fields, ",");
+        if ((fields.size()!=4)||(trim(fields[3]) != "2D;")) {
+          continue;
+        }
+        vector_string texunitf;
+        tokenize(trim(fields[2]), texunitf, "[]");
+        if ((texunitf.size()!=3)||(texunitf[0] != "texture")||(texunitf[2]!="")) {
+          continue;
+        }
+        int unit = atoi(texunitf[1].c_str());
+        if ((unit < 0) || (unit >= 32) || (shadowunit[unit]==false)) {
+          continue;
+        }
+        lines[lineno] = fields[0]+","+fields[1]+","+fields[2]+", SHADOW2D;";
+      }
+      string result = "!!ARBfp1.0\nOPTION ARB_fragment_program_shadow;\n";
+      for (int lineno=1; lineno<(int)lines.size(); lineno++) {
+        result += (lines[lineno] + "\n");
+      }
+      cgDestroyProgram(_cg_program[1]);
+      _cg_program[1] =
+        cgCreateProgram(_cg_context, CG_OBJECT, result.c_str(),
+                        _cg_profile[1], "fshader", (const char**)NULL);
+      print_cg_compile_errors(s->get_name(), _cg_context);
+      if (_cg_program[SHADER_type_frag]==0) {
+        release_resources();
+        return false;
+      }
+    }
+  }
+  
   bool success = true;
   bool success = true;
   CGparameter parameter;
   CGparameter parameter;
   for (int progindex=0; progindex<2; progindex++) {
   for (int progindex=0; progindex<2; progindex++) {

+ 4 - 3
panda/src/glstuff/glShaderContext_src.h

@@ -34,10 +34,11 @@ class CLP(GraphicsStateGuardian);
 
 
 class EXPCL_GL CLP(ShaderContext): public ShaderContext {
 class EXPCL_GL CLP(ShaderContext): public ShaderContext {
 public:
 public:
-  CLP(ShaderContext)(ShaderExpansion *s);
-  ~CLP(ShaderContext)();
   typedef CLP(GraphicsStateGuardian) GSG;
   typedef CLP(GraphicsStateGuardian) GSG;
 
 
+  CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg);
+  ~CLP(ShaderContext)();
+
   INLINE bool valid(void);
   INLINE bool valid(void);
   void bind(GSG *gsg);
   void bind(GSG *gsg);
   void unbind();
   void unbind();
@@ -116,7 +117,7 @@ private:
   vector <ShaderTransBind> _cg_parameter_bind;
   vector <ShaderTransBind> _cg_parameter_bind;
   vector <ShaderVarying> _cg_varying;
   vector <ShaderVarying> _cg_varying;
   
   
-  bool try_cg_compile(ShaderExpansion *s);
+  bool try_cg_compile(ShaderExpansion *s, GSG *gsg);
   void bind_cg_transform(const ShaderTransBind &stb,
   void bind_cg_transform(const ShaderTransBind &stb,
                          CLP(GraphicsStateGuardian) *gsg);
                          CLP(GraphicsStateGuardian) *gsg);
   void suggest_cg_profile(const string &vpro, const string &fpro);
   void suggest_cg_profile(const string &vpro, const string &fpro);

+ 5 - 1
panda/src/gobj/texture.cxx

@@ -1367,7 +1367,8 @@ string_filter_type(const string &string) {
     return FT_linear_mipmap_linear;
     return FT_linear_mipmap_linear;
   } else if (cmp_nocase_uh(string, "mipmap") == 0) {
   } else if (cmp_nocase_uh(string, "mipmap") == 0) {
     return FT_linear_mipmap_linear;
     return FT_linear_mipmap_linear;
-
+  } else if (cmp_nocase_uh(string, "shadow") == 0) {
+    return FT_shadow;
   } else {
   } else {
     return FT_invalid;
     return FT_invalid;
   }
   }
@@ -1923,6 +1924,9 @@ operator << (ostream &out, Texture::FilterType ft) {
   case Texture::FT_linear_mipmap_linear:
   case Texture::FT_linear_mipmap_linear:
     return out << "linear_mipmap_linear";
     return out << "linear_mipmap_linear";
 
 
+  case Texture::FT_shadow:
+    return out << "shadow";
+  
   case Texture::FT_invalid:
   case Texture::FT_invalid:
     return out << "invalid";
     return out << "invalid";
   }
   }

+ 3 - 0
panda/src/gobj/texture.h

@@ -127,6 +127,9 @@ PUBLISHED:
     // two mipmap levels, and linearly blend the results.
     // two mipmap levels, and linearly blend the results.
     FT_linear_mipmap_linear,
     FT_linear_mipmap_linear,
 
 
+    // The OpenGL ARB_shadow extension can be thought of as a kind of filtering.
+    FT_shadow,
+    
     // Returned by string_filter_type() for an invalid match.
     // Returned by string_filter_type() for an invalid match.
     FT_invalid
     FT_invalid
   };
   };