/* ID3DTexture2D* TW_LoadTextureFromTexture ( ID3DTexture2D* t_from, D3DFORMAT& t_dest_fmt, int levels_2_skip, u32& w, u32& h ) { // Calculate levels & dimensions ID3DTexture2D* t_dest = NULL; D3DSURFACE_DESC t_from_desc0 ; R_CHK (t_from->GetLevelDesc (0,&t_from_desc0)); int levels_exist = t_from->GetLevelCount(); int top_width = t_from_desc0.Width; int top_height = t_from_desc0.Height; Reduce (top_width,top_height,levels_exist,levels_2_skip); // Create HW-surface if (D3DX_DEFAULT==t_dest_fmt) t_dest_fmt = t_from_desc0.Format; R_CHK (D3DXCreateTexture( HW.pDevice, top_width,top_height, levels_exist,0,t_dest_fmt, D3DPOOL_MANAGED,&t_dest )); // Copy surfaces & destroy temporary ID3DTexture2D* T_src= t_from; ID3DTexture2D* T_dst= t_dest; int L_src = T_src->GetLevelCount ()-1; int L_dst = T_dst->GetLevelCount ()-1; for (; L_dst>=0; L_src--,L_dst--) { // Get surfaces IDirect3DSurface9 *S_src, *S_dst; R_CHK (T_src->GetSurfaceLevel (L_src,&S_src)); R_CHK (T_dst->GetSurfaceLevel (L_dst,&S_dst)); // Copy R_CHK (D3DXLoadSurfaceFromSurface(S_dst,NULL,NULL,S_src,NULL,NULL,D3DX_FILTER_NONE,0)); // Release surfaces _RELEASE (S_src); _RELEASE (S_dst); } // OK w = top_width; h = top_height; return t_dest; } template <class _It> IC void TW_Iterate_1OP ( ID3DTexture2D* t_dst, ID3DTexture2D* t_src, const _It pred ) { DWORD mips = t_dst->GetLevelCount(); R_ASSERT (mips == t_src->GetLevelCount()); for (DWORD i = 0; i < mips; i++) { D3DLOCKED_RECT Rsrc,Rdst; D3DSURFACE_DESC desc,descS; t_dst->GetLevelDesc (i, &desc); t_src->GetLevelDesc (i, &descS); VERIFY (desc.Format==descS.Format); VERIFY (desc.Format==D3DFMT_A8R8G8B8); t_src->LockRect (i,&Rsrc,0,0); t_dst->LockRect (i,&Rdst,0,0); for (u32 y = 0; y < desc.Height; y++) { for (u32 x = 0; x < desc.Width; x++) { DWORD& pSrc = *(((DWORD*)((BYTE*)Rsrc.pBits + (y * Rsrc.Pitch)))+x); DWORD& pDst = *(((DWORD*)((BYTE*)Rdst.pBits + (y * Rdst.Pitch)))+x); pDst = pred(pDst,pSrc); } } t_dst->UnlockRect (i); t_src->UnlockRect (i); } } template <class _It> IC void TW_Iterate_2OP ( ID3DTexture2D* t_dst, ID3DTexture2D* t_src0, ID3DTexture2D* t_src1, const _It pred ) { DWORD mips = t_dst->GetLevelCount(); R_ASSERT (mips == t_src0->GetLevelCount()); R_ASSERT (mips == t_src1->GetLevelCount()); for (DWORD i = 0; i < mips; i++) { D3DLOCKED_RECT Rsrc0,Rsrc1,Rdst; D3DSURFACE_DESC desc,descS0,descS1; t_dst->GetLevelDesc (i, &desc); t_src0->GetLevelDesc (i, &descS0); t_src1->GetLevelDesc (i, &descS1); VERIFY (desc.Format==descS0.Format); VERIFY (desc.Format==descS1.Format); VERIFY (desc.Format==D3DFMT_A8R8G8B8); t_src0->LockRect (i,&Rsrc0, 0,0); t_src1->LockRect (i,&Rsrc1, 0,0); t_dst->LockRect (i,&Rdst, 0,0); for (u32 y = 0; y < desc.Height; y++) { for (u32 x = 0; x < desc.Width; x++) { DWORD& pSrc0 = *(((DWORD*)((BYTE*)Rsrc0.pBits + (y * Rsrc0.Pitch)))+x); DWORD& pSrc1 = *(((DWORD*)((BYTE*)Rsrc1.pBits + (y * Rsrc1.Pitch)))+x); DWORD& pDst = *(((DWORD*)((BYTE*)Rdst.pBits + (y * Rdst.Pitch)))+x); pDst = pred(pDst,pSrc0,pSrc1); } } t_dst->UnlockRect (i); t_src0->UnlockRect (i); t_src1->UnlockRect (i); } } IC u32 it_gloss_rev (u32 d, u32 s) { return color_rgba ( color_get_A(s), // gloss color_get_B(d), color_get_G(d), color_get_R(d) ); } IC u32 it_gloss_rev_base(u32 d, u32 s) { u32 occ = color_get_A(d)/3; u32 def = 8; u32 gloss = (occ*1+def*3)/4; return color_rgba ( gloss, // gloss color_get_B(d), color_get_G(d), color_get_R(d) ); } IC u32 it_difference (u32 d, u32 orig, u32 ucomp) { return color_rgba( 128+(int(color_get_R(orig))-int(color_get_R(ucomp)))*2, // R-error 128+(int(color_get_G(orig))-int(color_get_G(ucomp)))*2, // G-error 128+(int(color_get_B(orig))-int(color_get_B(ucomp)))*2, // B-error 128+(int(color_get_A(orig))-int(color_get_A(ucomp)))*2 ); // A-error } IC u32 it_height_rev (u32 d, u32 s) { return color_rgba ( color_get_A(d), // diff x color_get_B(d), // diff y color_get_G(d), // diff z color_get_R(s) ); // height } IC u32 it_height_rev_base(u32 d, u32 s) { return color_rgba ( color_get_A(d), // diff x color_get_B(d), // diff y color_get_G(d), // diff z (color_get_R(s)+color_get_G(s)+color_get_B(s))/3 ); // height } */ ID3DBaseTexture* CRender::texture_load(LPCSTR fRName, u32& ret_msize, bool bStaging) { // Moved here just to avoid warning #ifdef USE_DX11 D3DX11_IMAGE_INFO IMG; #else D3DX10_IMAGE_INFO IMG; #endif ZeroMemory(&IMG, sizeof(IMG)); // Staging control static bool bAllowStaging = !strstr(Core.Params,"-no_staging"); bStaging &= bAllowStaging; ID3DBaseTexture* pTexture2D = NULL; //IDirect3DCubeTexture9* pTextureCUBE = NULL; string_path fn; //u32 dwWidth,dwHeight; u32 img_size = 0; int img_loaded_lod = 0; //D3DFORMAT fmt; u32 mip_cnt=u32(-1); // validation R_ASSERT (fRName); R_ASSERT (fRName[0]); // make file name string_path fname; xr_strcpy(fname,fRName); //. andy if (strext(fname)) *strext(fname)=0; fix_texture_name (fname); IReader* S = NULL; if (!FS.exist(fn,"$game_textures$", fname, ".dds") && strstr(fname,"_bump")) goto _BUMP_from_base; if (FS.exist(fn,"$level$", fname, ".dds")) goto _DDS; if (FS.exist(fn,"$game_saves$", fname, ".dds")) goto _DDS; if (FS.exist(fn,"$game_textures$", fname, ".dds")) goto _DDS; #ifdef _EDITOR ELog.Msg(mtError,"Can't find texture '%s'",fname); return 0; #else Msg("! Can't find texture '%s'",fname); R_ASSERT(FS.exist(fn,"$game_textures$", "ed\\ed_not_existing_texture",".dds")); goto _DDS; // Debug.fatal(DEBUG_INFO,"Can't find texture '%s'",fname); #endif _DDS: { // Load and get header S = FS.r_open (fn); #ifdef DEBUG Msg ("* Loaded: %s[%d]",fn,S->length()); #endif // DEBUG img_size = S->length (); R_ASSERT (S); //R_CHK2 (D3DXGetImageInfoFromFileInMemory (S->pointer(),S->length(),&IMG), fn); #ifdef USE_DX11 R_CHK2 (D3DX11GetImageInfoFromMemory(S->pointer(),S->length(), 0, &IMG, 0), fn); #else R_CHK2 (D3DX10GetImageInfoFromMemory(S->pointer(),S->length(), 0, &IMG, 0), fn); #endif //if (IMG.ResourceType == D3DRTYPE_CUBETEXTURE) goto _DDS_CUBE; if (IMG.MiscFlags & D3D_RESOURCE_MISC_TEXTURECUBE) goto _DDS_CUBE; else goto _DDS_2D; _DDS_CUBE: { //R_CHK(D3DXCreateCubeTextureFromFileInMemoryEx( // HW.pDevice, // S->pointer(),S->length(), // D3DX_DEFAULT, // IMG.MipLevels,0, // IMG.Format, // D3DPOOL_MANAGED, // D3DX_DEFAULT, // D3DX_DEFAULT, // 0,&IMG,0, // &pTextureCUBE // )); // Inited to default by provided default constructor #ifdef USE_DX11 D3DX11_IMAGE_LOAD_INFO LoadInfo; #else D3DX10_IMAGE_LOAD_INFO LoadInfo; #endif //LoadInfo.Usage = D3D_USAGE_IMMUTABLE; if (bStaging) { LoadInfo.Usage = D3D_USAGE_STAGING; LoadInfo.BindFlags = 0; LoadInfo.CpuAccessFlags = D3D_CPU_ACCESS_WRITE; } else { LoadInfo.Usage = D3D_USAGE_DEFAULT; LoadInfo.BindFlags = D3D_BIND_SHADER_RESOURCE; } LoadInfo.pSrcInfo = &IMG; #ifdef USE_DX11 R_CHK(D3DX11CreateTextureFromMemory( HW.pDevice, S->pointer(),S->length(), &LoadInfo, 0, &pTexture2D, 0 )); #else R_CHK(D3DX10CreateTextureFromMemory( HW.pDevice, S->pointer(),S->length(), &LoadInfo, 0, &pTexture2D, 0 )); #endif FS.r_close (S); // OK mip_cnt = IMG.MipLevels; ret_msize = calc_texture_size(img_loaded_lod, mip_cnt, img_size); return pTexture2D; } _DDS_2D: { // Check for LMAP and compress if needed strlwr (fn); // Load SYS-MEM-surface, bound to device restrictions //ID3DTexture2D* T_sysmem; //R_CHK2(D3DXCreateTextureFromFileInMemoryEx // ( // HW.pDevice,S->pointer(),S->length(), // D3DX_DEFAULT,D3DX_DEFAULT, // IMG.MipLevels,0, // IMG.Format, // D3DPOOL_SYSTEMMEM, // D3DX_DEFAULT, // D3DX_DEFAULT, // 0,&IMG,0, // &T_sysmem // ), fn); img_loaded_lod = get_texture_load_lod(fn); // Inited to default by provided default constructor #ifdef USE_DX11 D3DX11_IMAGE_LOAD_INFO LoadInfo; #else D3DX10_IMAGE_LOAD_INFO LoadInfo; #endif //LoadInfo.FirstMipLevel = img_loaded_lod; LoadInfo.Width = IMG.Width; LoadInfo.Height = IMG.Height; if (img_loaded_lod) { Reduce(LoadInfo.Width, LoadInfo.Height, IMG.MipLevels, img_loaded_lod); } //LoadInfo.Usage = D3D_USAGE_IMMUTABLE; if (bStaging) { LoadInfo.Usage = D3D_USAGE_STAGING; LoadInfo.BindFlags = 0; LoadInfo.CpuAccessFlags = D3D_CPU_ACCESS_WRITE; } else { LoadInfo.Usage = D3D_USAGE_DEFAULT; LoadInfo.BindFlags = D3D_BIND_SHADER_RESOURCE; } LoadInfo.pSrcInfo = &IMG; #ifdef USE_DX11 R_CHK2(D3DX11CreateTextureFromMemory ( HW.pDevice,S->pointer(),S->length(), &LoadInfo, 0, &pTexture2D, 0 ), fn); #else R_CHK2(D3DX10CreateTextureFromMemory ( HW.pDevice,S->pointer(),S->length(), &LoadInfo, 0, &pTexture2D, 0 ), fn); #endif FS.r_close (S); mip_cnt = IMG.MipLevels; // OK ret_msize = calc_texture_size(img_loaded_lod, mip_cnt, img_size); return pTexture2D; } } _BUMP_from_base: { //Msg ("! auto-generated bump map: %s",fname); Msg ("! Fallback to default bump map: %s",fname); ////////////////// if (strstr(fname,"_bump#")) { R_ASSERT2 (FS.exist(fn,"$game_textures$", "ed\\ed_dummy_bump#", ".dds"), "ed_dummy_bump#"); S = FS.r_open (fn); R_ASSERT2 (S, fn); img_size = S->length (); goto _DDS_2D; } if (strstr(fname,"_bump")) { R_ASSERT2 (FS.exist(fn,"$game_textures$", "ed\\ed_dummy_bump", ".dds"),"ed_dummy_bump"); S = FS.r_open (fn); R_ASSERT2 (S, fn); img_size = S->length (); goto _DDS_2D; } ////////////////// } return 0; }
ID3DBaseTexture* CRender::texture_load(LPCSTR fRName, u32& ret_msize) { ID3DTexture2D* pTexture2D = NULL; IDirect3DCubeTexture9* pTextureCUBE = NULL; string_path fn; u32 dwWidth,dwHeight; u32 img_size = 0; int img_loaded_lod = 0; D3DFORMAT fmt; u32 mip_cnt=u32(-1); // validation R_ASSERT (fRName); R_ASSERT (fRName[0]); // make file name string_path fname; xr_strcpy(fname,fRName); //. andy if (strext(fname)) *strext(fname)=0; fix_texture_name (fname); IReader* S = NULL; //if (FS.exist(fn,"$game_textures$",fname, ".dds") && strstr(fname,"_bump")) goto _BUMP; if (!FS.exist(fn,"$game_textures$", fname, ".dds") && strstr(fname,"_bump")) goto _BUMP_from_base; if (FS.exist(fn,"$level$", fname, ".dds")) goto _DDS; if (FS.exist(fn,"$game_saves$", fname, ".dds")) goto _DDS; if (FS.exist(fn,"$game_textures$", fname, ".dds")) goto _DDS; #ifdef _EDITOR ELog.Msg(mtError,"Can't find texture '%s'",fname); return 0; #else Msg("! Can't find texture '%s'",fname); R_ASSERT(FS.exist(fn,"$game_textures$", "ed\\ed_not_existing_texture",".dds")); goto _DDS; // Debug.fatal(DEBUG_INFO,"Can't find texture '%s'",fname); #endif _DDS: { // Load and get header D3DXIMAGE_INFO IMG; S = FS.r_open (fn); #ifdef DEBUG Msg ("* Loaded: %s[%d]b",fn,S->length()); #endif // DEBUG img_size = S->length (); R_ASSERT (S); HRESULT const result = D3DXGetImageInfoFromFileInMemory (S->pointer(),S->length(),&IMG); if ( FAILED(result) ) { Msg ("! Can't get image info for texture '%s'",fn); FS.r_close (S); string_path temp; R_ASSERT ( FS.exist( temp, "$game_textures$", "ed\\ed_not_existing_texture", ".dds" ) ); R_ASSERT ( xr_strcmp(temp,fn) ); xr_strcpy ( fn, temp ); goto _DDS; } if (IMG.ResourceType == D3DRTYPE_CUBETEXTURE) goto _DDS_CUBE; else goto _DDS_2D; _DDS_CUBE: { HRESULT const result = D3DXCreateCubeTextureFromFileInMemoryEx( HW.pDevice, S->pointer(),S->length(), D3DX_DEFAULT, IMG.MipLevels,0, IMG.Format, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0,&IMG,0, &pTextureCUBE ); FS.r_close (S); if ( FAILED(result) ) { Msg ("! Can't load texture '%s'",fn); string_path temp; R_ASSERT ( FS.exist( temp, "$game_textures$", "ed\\ed_not_existing_texture", ".dds" ) ); R_ASSERT ( xr_strcmp(temp,fn) ); xr_strcpy ( fn, temp ); goto _DDS; } // OK dwWidth = IMG.Width; dwHeight = IMG.Height; fmt = IMG.Format; ret_msize = calc_texture_size(img_loaded_lod, mip_cnt, img_size); mip_cnt = pTextureCUBE->GetLevelCount(); return pTextureCUBE; } _DDS_2D: { strlwr (fn); // Load SYS-MEM-surface, bound to device restrictions ID3DTexture2D* T_sysmem; HRESULT const result = D3DXCreateTextureFromFileInMemoryEx( HW.pDevice,S->pointer(),S->length(), D3DX_DEFAULT,D3DX_DEFAULT, IMG.MipLevels,0, IMG.Format, D3DPOOL_SYSTEMMEM, D3DX_DEFAULT, D3DX_DEFAULT, 0,&IMG,0, &T_sysmem ); FS.r_close (S); if ( FAILED(result) ) { Msg ("! Can't load texture '%s'",fn); string_path temp; R_ASSERT ( FS.exist( temp, "$game_textures$", "ed\\ed_not_existing_texture", ".dds" ) ); strlwr (temp); R_ASSERT ( xr_strcmp(temp,fn) ); xr_strcpy ( fn, temp ); goto _DDS; } img_loaded_lod = get_texture_load_lod(fn); pTexture2D = TW_LoadTextureFromTexture(T_sysmem,IMG.Format, img_loaded_lod, dwWidth, dwHeight); mip_cnt = pTexture2D->GetLevelCount(); _RELEASE (T_sysmem); // OK fmt = IMG.Format; ret_msize = calc_texture_size(img_loaded_lod, mip_cnt, img_size); return pTexture2D; } } /* _BUMP: { // Load SYS-MEM-surface, bound to device restrictions D3DXIMAGE_INFO IMG; IReader* S = FS.r_open (fn); msize = S->length (); ID3DTexture2D* T_height_gloss; R_CHK(D3DXCreateTextureFromFileInMemoryEx( HW.pDevice, S->pointer(),S->length(), D3DX_DEFAULT,D3DX_DEFAULT, D3DX_DEFAULT,0,D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, D3DX_DEFAULT,D3DX_DEFAULT, 0,&IMG,0,&T_height_gloss )); FS.r_close (S); //TW_Save (T_height_gloss,fname,"debug-0","original"); // Create HW-surface, compute normal map ID3DTexture2D* T_normal_1 = 0; R_CHK(D3DXCreateTexture (HW.pDevice,IMG.Width,IMG.Height,D3DX_DEFAULT,0,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&T_normal_1)); R_CHK(D3DXComputeNormalMap (T_normal_1,T_height_gloss,0,0,D3DX_CHANNEL_RED,_BUMPHEIGH)); //TW_Save (T_normal_1,fname,"debug-1","normal"); // Transfer gloss-map TW_Iterate_1OP (T_normal_1,T_height_gloss,it_gloss_rev); //TW_Save (T_normal_1,fname,"debug-2","normal-G"); // Compress fmt = D3DFMT_DXT5; ID3DTexture2D* T_normal_1C = TW_LoadTextureFromTexture(T_normal_1,fmt,psTextureLOD,dwWidth,dwHeight); //TW_Save (T_normal_1C,fname,"debug-3","normal-G-C"); #if RENDER==R_R2 // Decompress (back) fmt = D3DFMT_A8R8G8B8; ID3DTexture2D* T_normal_1U = TW_LoadTextureFromTexture(T_normal_1C,fmt,0,dwWidth,dwHeight); // TW_Save (T_normal_1U,fname,"debug-4","normal-G-CU"); // Calculate difference ID3DTexture2D* T_normal_1D = 0; R_CHK(D3DXCreateTexture(HW.pDevice,dwWidth,dwHeight,T_normal_1U->GetLevelCount(),0,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&T_normal_1D)); TW_Iterate_2OP (T_normal_1D,T_normal_1,T_normal_1U,it_difference); // TW_Save (T_normal_1D,fname,"debug-5","normal-G-diff"); // Reverse channels back + transfer heightmap TW_Iterate_1OP (T_normal_1D,T_height_gloss,it_height_rev); // TW_Save (T_normal_1D,fname,"debug-6","normal-G-diff-H"); // Compress fmt = D3DFMT_DXT5; ID3DTexture2D* T_normal_2C = TW_LoadTextureFromTexture(T_normal_1D,fmt,0,dwWidth,dwHeight); // TW_Save (T_normal_2C,fname,"debug-7","normal-G-diff-H-C"); _RELEASE (T_normal_1U ); _RELEASE (T_normal_1D ); // string256 fnameB; strconcat (fnameB,"$user$",fname,"X"); ref_texture t_temp = dxRenderDeviceRender::Instance().Resources->_CreateTexture (fnameB); t_temp->surface_set (T_normal_2C ); _RELEASE (T_normal_2C ); // texture should keep reference to it by itself #endif // release and return // T_normal_1C - normal.gloss, reversed // T_normal_2C - 2*error.height, non-reversed _RELEASE (T_height_gloss ); _RELEASE (T_normal_1 ); return T_normal_1C; } */ _BUMP_from_base: { Msg ("! auto-generated bump map: %s",fname); ////////////////// #ifndef _EDITOR if (strstr(fname,"_bump#")) { R_ASSERT2 (FS.exist(fn,"$game_textures$", "ed\\ed_dummy_bump#", ".dds"), "ed_dummy_bump#"); S = FS.r_open (fn); R_ASSERT2 (S, fn); img_size = S->length (); goto _DDS_2D; } if (strstr(fname,"_bump")) { R_ASSERT2 (FS.exist(fn,"$game_textures$", "ed\\ed_dummy_bump", ".dds"),"ed_dummy_bump"); S = FS.r_open (fn); R_ASSERT2 (S, fn); img_size = S->length (); goto _DDS_2D; } #endif ////////////////// *strstr (fname,"_bump") = 0; R_ASSERT2 (FS.exist(fn,"$game_textures$", fname, ".dds"),fname); // Load SYS-MEM-surface, bound to device restrictions D3DXIMAGE_INFO IMG; S = FS.r_open (fn); img_size = S->length (); ID3DTexture2D* T_base; R_CHK2(D3DXCreateTextureFromFileInMemoryEx( HW.pDevice, S->pointer(),S->length(), D3DX_DEFAULT,D3DX_DEFAULT, D3DX_DEFAULT,0,D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, D3DX_DEFAULT,D3DX_DEFAULT, 0,&IMG,0,&T_base ), fn); FS.r_close (S); // Create HW-surface ID3DTexture2D* T_normal_1 = 0; R_CHK(D3DXCreateTexture (HW.pDevice,IMG.Width,IMG.Height,D3DX_DEFAULT,0,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM, &T_normal_1)); R_CHK(D3DXComputeNormalMap (T_normal_1,T_base,0,D3DX_NORMALMAP_COMPUTE_OCCLUSION,D3DX_CHANNEL_LUMINANCE,_BUMPHEIGH)); // Transfer gloss-map TW_Iterate_1OP (T_normal_1,T_base,it_gloss_rev_base); // Compress fmt = D3DFMT_DXT5; img_loaded_lod = get_texture_load_lod(fn); ID3DTexture2D* T_normal_1C = TW_LoadTextureFromTexture(T_normal_1, fmt, img_loaded_lod, dwWidth, dwHeight); mip_cnt = T_normal_1C->GetLevelCount(); #if RENDER==R_R2 // Decompress (back) fmt = D3DFMT_A8R8G8B8; ID3DTexture2D* T_normal_1U = TW_LoadTextureFromTexture(T_normal_1C,fmt,0,dwWidth,dwHeight); // Calculate difference ID3DTexture2D* T_normal_1D = 0; R_CHK(D3DXCreateTexture(HW.pDevice,dwWidth,dwHeight,T_normal_1U->GetLevelCount(),0,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&T_normal_1D)); TW_Iterate_2OP (T_normal_1D,T_normal_1,T_normal_1U,it_difference); // Reverse channels back + transfer heightmap TW_Iterate_1OP (T_normal_1D,T_base,it_height_rev_base); // Compress fmt = D3DFMT_DXT5; ID3DTexture2D* T_normal_2C = TW_LoadTextureFromTexture(T_normal_1D,fmt,0,dwWidth,dwHeight); _RELEASE (T_normal_1U ); _RELEASE (T_normal_1D ); // string256 fnameB; strconcat (sizeof(fnameB),fnameB,"$user$",fname,"_bumpX"); ref_texture t_temp = dxRenderDeviceRender::Instance().Resources->_CreateTexture (fnameB); t_temp->surface_set (T_normal_2C ); _RELEASE (T_normal_2C ); // texture should keep reference to it by itself #endif // T_normal_1C - normal.gloss, reversed // T_normal_2C - 2*error.height, non-reversed _RELEASE (T_base); _RELEASE (T_normal_1); ret_msize = calc_texture_size(img_loaded_lod, mip_cnt, img_size); return T_normal_1C; } }