Пример #1
0
IDirect3DTexture9* Core::LoadTexture( IDirect3DDevice9* device, const tstring& file, u32* textureSize, bool* hasAlpha, D3DPOOL pool )
{
  IDirect3DTexture9* texture = NULL;
  bool alpha = false;

  if (!file.empty())
  {
      if ( Helium::Path( file ).Exists() )
    {
      D3DFORMAT textureFormat = D3DFMT_DXT1; 

      D3DXIMAGE_INFO sourceInfo;
      LPDIRECT3DTEXTURE9 tempTexture;
    
      if ( D3DXCreateTextureFromFileEx( device,
                                        file.c_str(),
                                        D3DX_DEFAULT,
                                        D3DX_DEFAULT,
                                        D3DX_DEFAULT,
                                        NULL,
                                        D3DFMT_A8R8G8B8,
                                        pool,
                                        D3DX_DEFAULT,        // filter? 
                                        D3DX_FILTER_NONE,    // mip filter
                                        NULL,
                                        &sourceInfo,
                                        NULL,
                                        &tempTexture ) == D3D_OK )
      {
        // lock the first mip level, and iterate over all pixels looking for
        // alpha != 0 || alpha != 255
        D3DLOCKED_RECT lockedRect; 
        HRESULT locked = tempTexture->LockRect(0, &lockedRect, NULL, D3DLOCK_READONLY); 
        
        D3DSURFACE_DESC desc; 
        tempTexture->GetLevelDesc(0, &desc); 

        for(u32 r = 0; r < desc.Height && textureFormat == D3DFMT_DXT1; r++)
        {
          u32* pixels = (u32*) (((u8*)lockedRect.pBits) + lockedRect.Pitch * r); 
          for(u32 c = 0; c < desc.Width; c++)
          {
            u32 masked = pixels[c] & 0xFF000000; 
            if(masked != 0xFF000000)
            {
              alpha = true; 
            }
            if(masked != 0xFF000000 && masked != 0x00000000)
            {
              textureFormat = D3DFMT_DXT5; 
              break; 
            }
          }
        }

        tempTexture->UnlockRect(0);

        tempTexture->Release(); 
      }

      int compressionRatio;
      switch ( textureFormat )
      {
      case D3DFMT_DXT1:
        {
          if (alpha)
          {
            compressionRatio = 8;
          }
          else
          {
            compressionRatio = 6;
          }
          break;
        }

      case D3DFMT_DXT5:
        {
          compressionRatio = 4;
          break;
        }

      default:
        {
          compressionRatio = 1;
          HELIUM_BREAK();
          break;
        }
      }

      if ( D3DXCreateTextureFromFileEx( device,
                                        file.c_str(),
                                        D3DX_DEFAULT,
                                        D3DX_DEFAULT,
                                        D3DX_DEFAULT,
                                        NULL,
                                        textureFormat, 
                                        pool,
                                        D3DX_DEFAULT,
                                        D3DX_DEFAULT,
                                        NULL,
                                        &sourceInfo,
                                        NULL,
                                        &texture ) == D3D_OK )
      {
        texture->SetAutoGenFilterType( D3DTEXF_ANISOTROPIC );

        if ( textureSize )
        {
          *textureSize = 0; 
          for(u32 i = 0; i < texture->GetLevelCount(); i++)
          {
            D3DSURFACE_DESC desc; 
            texture->GetLevelDesc(i, &desc); 
            *textureSize += desc.Width * desc.Height * 4 / compressionRatio;
          }
        }
      }
      else
      {
        Log::Warning( TXT( "Unable to create texture from file '%s'\n" ), file.c_str() );
      }
    }
    else
    {
      Log::Warning( TXT( "File '%s' does not exist\n" ), file.c_str() );
    }
  }

  if ( hasAlpha )
  {
    *hasAlpha = alpha;
  }

  return texture;
}