소스 검색

fix texture filtering and blending

georges 25 년 전
부모
커밋
d0aee9aed7

+ 30 - 0
panda/src/dxgsg/dxGraphicsStateGuardian.I

@@ -631,6 +631,10 @@ enable_texturing(bool val) {
     _texturing_enabled = val;
   } 
 
+//  assert(_pCurTexContext!=NULL);  we're definitely called with it NULL for both true and false
+
+/*
+old way to disable texturing
   if(val == FALSE) {
       _d3dDevice->SetTexture(0,NULL);
   } else {
@@ -638,6 +642,32 @@ enable_texturing(bool val) {
         _d3dDevice->SetTexture(0,_pCurTexContext->_surface);
       }
   }
+*/  
+
+  if(val == FALSE) {
+      if(_pCurTexContext!=NULL) {
+          _d3dDevice->GetTextureStageState(0,D3DTSS_COLOROP,(DWORD*)&(_pCurTexContext->_SavedStage0_ColorOp));
+      }
+      _d3dDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE);
+  } else {
+        // note: if we set D3DTSS_COLOROP to something other than disable and then
+        // call "enable_texturing(), conflict will occur
+     #if 0
+     // we need to set D3DTSS_COLOROP,D3DTOP_MODULATE if pCurTextContext is null and tex enabled true,
+     // so this test is impossible now
+        DWORD dwColOpVal=0;
+        _d3dDevice->GetTextureStageState(0,D3DTSS_COLOROP,&dwColOpVal);        
+        if(dwColOpVal!=D3DTOP_DISABLE) {
+              dxgsg_cat.error() << "Error in enable_texturing(true), someone set D3DTSS_COLOROP to non-disabled value\n";
+        }
+     #endif
+        if(_pCurTexContext!=NULL) {     
+            _d3dDevice->SetTextureStageState(0,D3DTSS_COLOROP,_pCurTexContext->_SavedStage0_ColorOp);
+        } else {
+            // not sure this is the right thing to do
+            _d3dDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
+        }
+  }
 }
 
 

+ 145 - 43
panda/src/dxgsg/dxGraphicsStateGuardian.cxx

@@ -125,7 +125,7 @@ DXGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) {
 DXGraphicsStateGuardian::
 ~DXGraphicsStateGuardian() {
   if (_d3dDevice != NULL)
-     _d3dDevice->SetTexture(0, NULL);
+     _d3dDevice->SetTexture(0, NULL);  // this frees reference to the old texture
   _pCurTexContext = NULL;
 
   free_pointers();
@@ -395,6 +395,29 @@ init_dx(  LPDIRECTDRAW7		context,
   if(((dx_decal_type==GDT_blend)||(dx_decal_type==GDT_mask)) && !(D3DDevDesc.dpcTriCaps.dwMiscCaps & D3DPMISCCAPS_MASKZ))
          dxgsg_cat.error() << "dx-decal-type mask impossible to implement, no hardware support for Z-masking, decals will not appear correctly\n";
 
+#define REQUIRED_BLENDCAPS (D3DPBLENDCAPS_ZERO|D3DPBLENDCAPS_ONE|D3DPBLENDCAPS_SRCCOLOR|D3DPBLENDCAPS_INVSRCCOLOR| \
+                            D3DPBLENDCAPS_SRCALPHA|D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA|D3DPBLENDCAPS_INVDESTALPHA|D3DPBLENDCAPS_DESTCOLOR|D3DPBLENDCAPS_INVDESTCOLOR)
+
+  if(((D3DDevDesc.dpcTriCaps.dwSrcBlendCaps & REQUIRED_BLENDCAPS)!=REQUIRED_BLENDCAPS) ||
+     ((D3DDevDesc.dpcTriCaps.dwDestBlendCaps & REQUIRED_BLENDCAPS)!=REQUIRED_BLENDCAPS)) {
+         dxgsg_cat.error() << "device is missing texture blending capabilities, blending may not work correctly\n";
+  }
+
+  if(!(D3DDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_TRANSPARENCY)) {
+         dxgsg_cat.error() << "device is missing texture transparency capability, transparency will work correctly!!!\n";
+  }
+
+  // just require trilinear.  if it can do that, it can probably do all the lesser point-sampling variations too
+#define REQUIRED_TEXFILTERCAPS (D3DPTFILTERCAPS_MAGFLINEAR |  D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_LINEAR)
+  if((D3DDevDesc.dpcTriCaps.dwTextureFilterCaps & REQUIRED_TEXFILTERCAPS)!=REQUIRED_TEXFILTERCAPS) {
+         dxgsg_cat.error() << "device is missing texture bilinear filtering capability, textures may appear blocky!!!\n";
+  }
+
+#define REQUIRED_MIPMAP_TEXFILTERCAPS (D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR)
+  if((D3DDevDesc.dpcTriCaps.dwTextureFilterCaps & REQUIRED_MIPMAP_TEXFILTERCAPS)!=REQUIRED_MIPMAP_TEXFILTERCAPS) {
+         dxgsg_cat.error() << "device is missing tri-linear mipmap filtering capability, texture mipmaps may not supported!!!\n";
+  }
+
   SetRect(&clip_rect, 0,0,0,0);		// no clip rect set
 
   _d3dDevice->SetRenderState(D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1);
@@ -451,7 +474,9 @@ init_dx(  LPDIRECTDRAW7		context,
   dwa->issue(this);
   cfa->issue(this);
   la->issue(this);
-  ta->issue(this);
+
+  _d3dDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE);  // disables texturing
+  ta->issue(this); // no curtextcontext, this does nothing.  dx should already be properly inited above anyway
 
 }
 
@@ -3219,8 +3244,8 @@ issue_color_blend(const ColorBlendAttribute *attrib) {
 	call_dxBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
     break;
   default:
-    dxgsg_cat.error()
-      << "Unknown color blend mode " << (int)mode << endl;
+  dxgsg_cat.error()
+    << "Unknown color blend mode " << (int)mode << endl;
     break;
   }
 }
@@ -3232,14 +3257,80 @@ issue_color_blend(const ColorBlendAttribute *attrib) {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian::
 issue_texture_apply(const TextureApplyAttribute *attrib) {
-  //dxgsg_cat.spam() << "DXGSG issue_texture_apply null-up!!";   //bugbug: useless
-  return;
 
-  activate();
-#ifdef WBD_GL_MODE
-  GLint glmode = get_texture_apply_mode_type(attrib->get_mode());
-  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, glmode);
-#endif				// WBD_GL_MODE
+   switch(attrib->get_mode()) {
+       case TextureApplyProperty::M_modulate: 
+           // emulates GL_MODULATE glTexEnv mode
+           // want to multiply tex-color*pixel color to emulate GL modulate blend (see glTexEnv)
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
+
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
+
+           break;
+       case TextureApplyProperty::M_decal:
+           // emulates GL_DECAL glTexEnv mode
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_BLENDTEXTUREALPHA );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
+
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG2 );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
+
+           break;           
+       case TextureApplyProperty::M_replace: 
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1 );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
+
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1 );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
+           break;           
+       case TextureApplyProperty::M_add: 
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_ADD );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
+
+           // since I'm making up 'add' mode, use modulate.  "adding" alpha never makes sense right?
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
+
+           break;           
+       case TextureApplyProperty::M_blend: 
+           dxgsg_cat.error()
+             << "Impossible to emulate GL_BLEND in DX exactly " << (int) attrib->get_mode() << endl;
+/*
+           // emulate GL_BLEND glTexEnv
+           
+           GL requires 2 independent operations on 3 input vars for this mode
+           DX texture pipeline requires re-using input of last stage on each new op, so I dont think 
+           exact emulation is possible
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE | D3DTA_COMPLEMENT );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
+
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
+           _d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
+
+           need to SetTexture(1,tex) also
+           _d3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_MODULATE ); wrong
+           _d3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
+           _d3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TFACTOR );
+
+           _d3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1 );
+           _d3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
+*/
+
+
+           break;
+        default:
+            dxgsg_cat.error() << "Unknown texture blend mode " << (int) attrib->get_mode() << endl;
+            break;
+   }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -3797,10 +3888,49 @@ specify_texture(Texture *tex) {
 				  get_texture_wrap_mode(tex->get_wrapu()));
   _d3dDevice->SetTextureStageState(0,D3DTSS_ADDRESSV,
 				  get_texture_wrap_mode(tex->get_wrapv()));
-  _d3dDevice->SetTextureStageState(0,D3DTSS_MINFILTER,  
-				  get_texture_filter_type(tex->get_minfilter()));
-  _d3dDevice->SetTextureStageState(0,D3DTSS_MAGFILTER,  
-				  get_texture_filter_type(tex->get_magfilter()));
+
+  Texture::FilterType ft=tex->get_magfilter();
+
+  switch(ft) {
+      case Texture::FT_nearest:
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_POINT);
+          break;
+      case Texture::FT_linear:
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
+          break;
+      default:
+          dxgsg_cat.error() << "MipMap filter type setting for texture magfilter makes no sense,  texture: " << tex->get_name() << "\n";       
+          break;
+  }
+  
+  ft=tex->get_minfilter();
+
+  switch(ft) {
+      case Texture::FT_nearest:
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_POINT);
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_NONE);
+          break;
+      case Texture::FT_linear:
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_NONE);
+          break;
+      case Texture::FT_nearest_mipmap_nearest:
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_POINT);
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_POINT);
+          break;
+      case Texture::FT_linear_mipmap_nearest:
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_POINT);
+          break;
+      case Texture::FT_nearest_mipmap_linear:
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_POINT);
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
+          break;
+      case Texture::FT_linear_mipmap_linear:
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
+          _d3dDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTFP_LINEAR);
+          break;
+  }
 }
 
 
@@ -3877,34 +4007,6 @@ get_texture_wrap_mode(Texture::WrapMode wm) {
   return D3DTADDRESS_WRAP;
 }
 
-
-////////////////////////////////////////////////////////////////////
-//     Function: DXGraphicsStateGuardian::get_texture_filter_type
-//       Access: Protected
-//  Description: Maps from the Texture's internal filter type symbols
-//               to GL's.
-////////////////////////////////////////////////////////////////////
-D3DTEXTUREMAGFILTER DXGraphicsStateGuardian::
-get_texture_filter_type(Texture::FilterType ft) {
-  switch (ft) {
-  case Texture::FT_nearest:
-    return D3DTFG_POINT;
-  case Texture::FT_linear:
-    return D3DTFG_LINEAR;
-  case Texture::FT_nearest_mipmap_nearest:
-    return D3DTFG_POINT;
-  case Texture::FT_linear_mipmap_nearest:
-    return D3DTFG_LINEAR;
-  case Texture::FT_nearest_mipmap_linear:
-    return D3DTFG_POINT;
-  case Texture::FT_linear_mipmap_linear:
-    return D3DTFG_LINEAR;
-  }
-  dxgsg_cat.error() << "Invalid Texture::FilterType value!\n";
-  return D3DTFG_POINT;
-}
-
-
 ////////////////////////////////////////////////////////////////////
 //     Function: DXGraphicsStateGuardian::get_depth_func_type
 //       Access: Protected

+ 0 - 1
panda/src/dxgsg/dxGraphicsStateGuardian.h

@@ -293,7 +293,6 @@ protected:
   bool enable_light(int light, bool val);
 
   D3DTEXTUREADDRESS get_texture_wrap_mode(Texture::WrapMode wm);
-  D3DTEXTUREMAGFILTER get_texture_filter_type(Texture::FilterType ft);
   D3DCMPFUNC get_depth_func_type(DepthTestProperty::Mode m) const;
   D3DCMPFUNC get_stencil_func_type(StencilProperty::Mode m) const;
   D3DSTENCILOP get_stencil_action_type(StencilProperty::Action a) const;

+ 5 - 4
panda/src/dxgsg/dxTextureContext.cxx

@@ -310,7 +310,7 @@ CreateTexture( HDC hdc, LPDIRECT3DDEVICE7 pd3dDevice, int cNumTexPixFmts, LPDDPI
 
     szErrorMsg = "CreateTexture failed: couldn't find compatible Tex DDPIXELFORMAT!  \n";
 
-    dxgsg_cat.debug() << "CreateTexture handling bitdepth: " << bpp << " alphabits: " << cNumAlphaBits << "\n";
+    dxgsg_cat.spam() << "CreateTexture handling bitdepth: " << bpp << " alphabits: " << cNumAlphaBits << "\n";
 
     // Mark formats I dont want to deal with
     for(i=0,pCurPixFmt=pTexPixFmts;i<cNumTexPixFmts;i++,pCurPixFmt++) {
@@ -535,7 +535,7 @@ CreateTexture( HDC hdc, LPDIRECT3DDEVICE7 pd3dDevice, int cNumTexPixFmts, LPDDPI
         DWORD x,y,dwPixel;
 
 #ifdef _DEBUG
-        dxgsg_cat.debug() << "CreateTexture executing conversion " << ConvNameStrs[ConvNeeded] << "\n";    
+        dxgsg_cat.spam() << "CreateTexture executing conversion " << ConvNameStrs[ConvNeeded] << "\n";    
 #endif
 
         switch(ConvNeeded) {
@@ -848,17 +848,18 @@ DXTextureContext(Texture *tex) :
   TextureContext(tex)
 {
 #ifdef _DEBUG
-  dxgsg_cat.debug() << "Making DX texture for " << tex->get_name() << "\n";
+  dxgsg_cat.spam() << "Making DX texture for " << tex->get_name() << "\n";
 #endif
   _surface = NULL;
   _tex = tex;
+ _SavedStage0_ColorOp=D3DTOP_MODULATE;  // this is default when texturing is enabled
 }
 
 DXTextureContext::
 ~DXTextureContext()
 {
 #ifdef _DEBUG
-    dxgsg_cat.debug() << "Deleting DX texture for " << _tex->get_name() << "\n";    
+    dxgsg_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n";    
 #endif
 	DeleteTexture();
 	TextureContext::~TextureContext();

+ 1 - 0
panda/src/dxgsg/dxTextureContext.h

@@ -31,6 +31,7 @@ public:
 
   LPDIRECTDRAWSURFACE7  _surface;
   Texture *_tex;            // ptr to parent, primarily for access to namestr
+  D3DTEXTUREOP _SavedStage0_ColorOp;
 
   LPDIRECTDRAWSURFACE7 CreateTexture( HDC hdc, LPDIRECT3DDEVICE7 pd3dDevice, int cNumTexPixFmts, LPDDPIXELFORMAT pTexPixFmts);
   void DeleteTexture();