first success, and need test
This commit is contained in:
parent
ccccc39a4a
commit
78ac5d9b40
@ -53,8 +53,11 @@ target_link_libraries(TexConv PRIVATE CMCore CMPlatform CMUtil
|
||||
Qt5::Core Qt5::Gui Qt5::Widgets
|
||||
DevIL ILU)
|
||||
|
||||
add_executable(MicroPBR MicroPBR.cpp YUV.cpp ${ILIMAGE_SOURCE})
|
||||
target_link_libraries(MicroPBR PRIVATE CMCore CMPlatform CMUtil DevIL ILU)
|
||||
add_executable(MicroPBR MicroPBR.cpp YUV.cpp SpheremapNormal.cpp ${ILIMAGE_SOURCE})
|
||||
target_link_libraries(MicroPBR PRIVATE CMCore CMPlatform CMUtil DevIL ILU MathGeoLib)
|
||||
|
||||
add_executable(YUVTest YUVTest.cpp YUV.cpp ${ILIMAGE_SOURCE})
|
||||
target_link_libraries(YUVTest PRIVATE CMCore CMPlatform CMUtil DevIL ILU)
|
||||
add_executable(YUVTest YUVTest.cpp YUV.cpp SpheremapNormal.cpp ${ILIMAGE_SOURCE})
|
||||
target_link_libraries(YUVTest PRIVATE CMCore CMPlatform CMUtil DevIL ILU)
|
||||
|
||||
add_executable(NormalTest NormalTest.cpp SpheremapNormal.cpp ${ILIMAGE_SOURCE})
|
||||
target_link_libraries(NormalTest PRIVATE CMCore CMPlatform CMUtil DevIL ILU MathGeoLib)
|
@ -39,10 +39,16 @@ public:
|
||||
~ILImage();
|
||||
|
||||
bool LoadFile(const OSString &);
|
||||
bool SaveFile(const OSString &);
|
||||
|
||||
bool Create(ILuint w,ILuint h,ILuint c,ILuint t,void *);
|
||||
|
||||
void Bind();
|
||||
|
||||
bool Resize(uint,uint);
|
||||
|
||||
void ToRGB(ILuint type=IL_UNSIGNED_BYTE);
|
||||
void ToGray(ILuint type=IL_UNSIGNED_BYTE);
|
||||
|
||||
void *GetR(ILuint type);
|
||||
|
||||
@ -51,4 +57,6 @@ public:
|
||||
// void *GetBGR(ILuint type){return GetData(IL_BGR,type);}
|
||||
void *GetRGBA(ILuint type){return GetData(IL_RGBA,type);}
|
||||
// void *GetBGRA(ILuint type){return GetData(IL_BGRA,type);}
|
||||
|
||||
void *GetLum(ILuint type){return GetData(IL_LUMINANCE,type);}
|
||||
};//class ILImage
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include"ILImage.h"
|
||||
#include<IL/ilu.h>
|
||||
#include<hgl/log/LogInfo.h>
|
||||
#include<hgl/filesystem/FileSystem.h>
|
||||
|
||||
using namespace hgl;
|
||||
|
||||
@ -56,6 +57,32 @@ ILImage::~ILImage()
|
||||
ilDeleteImages(1,&il_index);
|
||||
}
|
||||
|
||||
bool ILImage::Create(ILuint w,ILuint h,ILuint c,ILuint t,void *data)
|
||||
{
|
||||
const ILenum format[]=
|
||||
{
|
||||
IL_LUMINANCE,
|
||||
IL_LUMINANCE_ALPHA,
|
||||
IL_RGB,
|
||||
IL_RGBA,
|
||||
};
|
||||
|
||||
if(c<1||c>4)return(false);
|
||||
|
||||
Bind();
|
||||
|
||||
ilClearImage();
|
||||
return ilTexImage(w,h,1,c,format[c-1],t,data);
|
||||
}
|
||||
|
||||
bool ILImage::SaveFile(const OSString &filename)
|
||||
{
|
||||
Bind();
|
||||
ilEnable(IL_FILE_OVERWRITE);
|
||||
|
||||
return ilSaveImage(filename.c_str());
|
||||
}
|
||||
|
||||
void ILImage::Bind()
|
||||
{
|
||||
ilBindImage(il_index);
|
||||
@ -87,6 +114,12 @@ bool ILImage::LoadFile(const OSString &filename)
|
||||
{
|
||||
Bind();
|
||||
|
||||
if(!filesystem::FileExist(filename))
|
||||
{
|
||||
LOG_INFO(OS_TEXT("Can't find filename: ")+filename);
|
||||
return(false);
|
||||
}
|
||||
|
||||
if(!ilLoadImage(filename.c_str()))
|
||||
return(false);
|
||||
|
||||
@ -139,6 +172,18 @@ bool ILImage::LoadFile(const OSString &filename)
|
||||
return(true);
|
||||
}
|
||||
|
||||
void ILImage::ToRGB(ILuint type)
|
||||
{
|
||||
if(il_format!=IL_RGB)
|
||||
Convert(IL_RGB,type);
|
||||
}
|
||||
|
||||
void ILImage::ToGray(ILuint type)
|
||||
{
|
||||
if(il_format!=IL_LUMINANCE)
|
||||
Convert(IL_LUMINANCE,type);
|
||||
}
|
||||
|
||||
void *ILImage::GetR(ILuint type)
|
||||
{
|
||||
Bind();
|
||||
|
247
MicroPBR.cpp
247
MicroPBR.cpp
@ -1,4 +1,5 @@
|
||||
#include<iostream>
|
||||
#include<iomanip>
|
||||
#include<ILImage.h>
|
||||
#include<hgl/type/DataType.h>
|
||||
#include<hgl/util/cmd/CmdParse.h>
|
||||
@ -6,36 +7,99 @@
|
||||
using namespace hgl;
|
||||
using namespace hgl::util;
|
||||
|
||||
void RGB2YUV(uint8 *y,uint8 *u,uint8 *v,const uint8 *rgb,int w,int h);
|
||||
#if HGL_OS == HGL_OS_Windows
|
||||
#define std_cout std::wcout
|
||||
#else
|
||||
#define std_cout std::cout
|
||||
#endif//
|
||||
|
||||
class PBRComponent
|
||||
namespace hgl
|
||||
{
|
||||
OSString name;
|
||||
void RGB2YUV(uint8 *y,uint8 *u,uint8 *v,const uint8 *rgb,const uint w,const uint h);
|
||||
void normal_compress(uint8 *x,uint8 *y,const uint8 *rgb,const uint count);
|
||||
|
||||
ILImage img;
|
||||
|
||||
public:
|
||||
|
||||
PBRComponent(const OSString &cn)
|
||||
template<typename T>
|
||||
void MixRGB(T *rgb,const T *r,const T *g,const T *b,const uint count)
|
||||
{
|
||||
name=cn;
|
||||
for(uint i=0;i<count;i++)
|
||||
{
|
||||
*rgb=*r;++rgb;++r;
|
||||
*rgb=*g;++rgb;++g;
|
||||
*rgb=*b;++rgb;++b;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~PBRComponent()=default;
|
||||
|
||||
bool Load(const OSString &fn)
|
||||
template<typename T>
|
||||
void MixRGBA(T *rgba,const T *r,const T *g,const T *b,const T *a,const uint count)
|
||||
{
|
||||
for(uint i=0;i<count;i++)
|
||||
{
|
||||
*rgba=*r;++rgba;++r;
|
||||
*rgba=*g;++rgba;++g;
|
||||
*rgba=*b;++rgba;++b;
|
||||
*rgba=*a;++rgba;++a;
|
||||
}
|
||||
}
|
||||
};//class PBRComponent
|
||||
|
||||
class PBRComponent
|
||||
{
|
||||
OSString param_name;
|
||||
OSString name;
|
||||
OSString filename;
|
||||
|
||||
bool has;
|
||||
ILImage img;
|
||||
|
||||
public:
|
||||
|
||||
const uint width()const{return img.width();}
|
||||
const uint height()const{return img.height();}
|
||||
|
||||
public:
|
||||
|
||||
PBRComponent(const OSString &cn,const OSString &pn)
|
||||
{
|
||||
param_name=pn;
|
||||
name=cn;
|
||||
has=false;
|
||||
}
|
||||
|
||||
virtual ~PBRComponent()=default;
|
||||
|
||||
const bool isHas()const{return has;}
|
||||
|
||||
bool Parse(const CmdParse &cp)
|
||||
{
|
||||
has=cp.GetString(param_name,filename);
|
||||
if(!has)
|
||||
{
|
||||
std_cout<<OS_TEXT("no ")<<std::setw(10)<<name.c_str()<<std::endl;
|
||||
return(false);
|
||||
}
|
||||
|
||||
std_cout<<std::setw(10)<<name.c_str()<<": "<<filename.c_str()<<std::endl;
|
||||
|
||||
has=img.LoadFile(filename);
|
||||
|
||||
if(!has)
|
||||
std_cout<<OS_TEXT("Load file failed, filename: ")<<filename.c_str()<<std::endl;
|
||||
|
||||
return(has);
|
||||
}
|
||||
|
||||
void Resize(const uint w,const uint h){img.Resize(w,h);}
|
||||
void ToRGB(){img.ToRGB();}
|
||||
void ToGray(){img.ToGray();}
|
||||
|
||||
uint8 *GetRGB(){return (uint8 *)img.GetRGB(IL_UNSIGNED_BYTE);}
|
||||
uint8 *GetLum(){return (uint8 *)img.GetLum(IL_UNSIGNED_BYTE);}
|
||||
};//class PBRComponent
|
||||
}//namespace hgl
|
||||
|
||||
#if HGL_OS == HGL_OS_Windows
|
||||
#define std_cout std::wcout
|
||||
|
||||
int wmain(int argc,wchar_t **argv)
|
||||
int wmain(int argc,wchar_t **argv)
|
||||
#else
|
||||
|
||||
#define std_cout std::cout
|
||||
int main(int argc,char **argv)
|
||||
int main(int argc,char **argv)
|
||||
#endif//
|
||||
{
|
||||
std::cout<<"MicroPBR Texture Compression"<<std::endl<<std::endl;
|
||||
@ -49,38 +113,135 @@ int main(int argc,char **argv)
|
||||
|
||||
CmdParse cp(argc,argv);
|
||||
|
||||
OSString color_filename,
|
||||
normal_filename,
|
||||
metallic_filename,
|
||||
roughness_filename;
|
||||
PBRComponent color (OS_TEXT("BaseColor"),OS_TEXT("/C:")),
|
||||
normal (OS_TEXT("Normal" ),OS_TEXT("/N:")),
|
||||
metallic (OS_TEXT("Metallic" ),OS_TEXT("/M:")),
|
||||
roughness (OS_TEXT("Roughness"),OS_TEXT("/R:"));
|
||||
|
||||
bool has_color,
|
||||
has_normal,
|
||||
has_metallic,
|
||||
has_roughness;
|
||||
ilInit();
|
||||
|
||||
has_color =cp.GetString(OS_TEXT("/C:"),color_filename);
|
||||
has_normal =cp.GetString(OS_TEXT("/N:"),normal_filename);
|
||||
has_metallic =cp.GetString(OS_TEXT("/M:"),metallic_filename);
|
||||
has_roughness =cp.GetString(OS_TEXT("/R:"),roughness_filename);
|
||||
color.Parse(cp);
|
||||
normal.Parse(cp);
|
||||
metallic.Parse(cp);
|
||||
roughness.Parse(cp);
|
||||
|
||||
if(has_color )std_cout<<OS_TEXT("BaseColor: ")<<color_filename.c_str()<<std::endl;
|
||||
if(has_normal )std_cout<<OS_TEXT(" Normal: ")<<normal_filename.c_str()<<std::endl;
|
||||
if(has_metallic )std_cout<<OS_TEXT(" Metallic: ")<<metallic_filename.c_str()<<std::endl;
|
||||
if(has_roughness )std_cout<<OS_TEXT("Roughness: ")<<roughness_filename.c_str()<<std::endl;
|
||||
if(!color.isHas()||!normal.isHas())
|
||||
return(false);
|
||||
|
||||
std_cout<<OS_TEXT("Output: ")<<argv[1]<<OS_TEXT("_YNormal.png")<<std::endl;
|
||||
std_cout<<OS_TEXT("Output: ")<<argv[1]<<OS_TEXT("_UVMR.png")<<std::endl;
|
||||
color.ToRGB();
|
||||
normal.ToRGB();
|
||||
|
||||
ILImage color,normal,metallic,roughness;
|
||||
ILImage yn,uvmr;
|
||||
if(color.width()!=normal.width()
|
||||
||color.height()!=normal.height())
|
||||
{
|
||||
uint nw=hgl_min(color.width(),normal.width());
|
||||
uint nh=hgl_max(color.height(),normal.height());
|
||||
|
||||
if(has_color&&!color.LoadFile(color_filename))return(1);
|
||||
if(has_normal&&!normal.LoadFile(normal_filename))return(2);
|
||||
if(has_metallic&&!metallic.LoadFile(metallic_filename))return(3);
|
||||
if(has_roughness&&!roughness.LoadFile(roughness_filename))return(4);
|
||||
color.Resize(nw,nh);
|
||||
}
|
||||
|
||||
const uint w=color.width();
|
||||
const uint h=color.height();
|
||||
const uint half_w=w>>1;
|
||||
const uint half_h=h>>1;
|
||||
|
||||
if(metallic.isHas())
|
||||
{
|
||||
metallic.ToGray();
|
||||
metallic.Resize(half_w,half_h);
|
||||
}
|
||||
|
||||
if(roughness.isHas())
|
||||
{
|
||||
roughness.ToGray();
|
||||
roughness.Resize(half_w,half_h);
|
||||
}
|
||||
|
||||
uint8 *y,*u,*v,*nx,*ny;
|
||||
|
||||
y=new uint8[w*h];
|
||||
u=new uint8[half_w*half_h];
|
||||
v=new uint8[half_w*half_h];
|
||||
nx=new uint8[w*h];
|
||||
ny=new uint8[w*h];
|
||||
|
||||
RGB2YUV(y,u,v,color.GetRGB(),w,h);
|
||||
normal_compress(nx,ny,normal.GetRGB(),w*h);
|
||||
|
||||
// BaseColor Y + Normal XY
|
||||
{
|
||||
ILImage img;
|
||||
const OSString out_filename=OSString(argv[1])+OS_TEXT("_YN.png");
|
||||
|
||||
uint8 *pixels=new uint8[w*h*3];
|
||||
|
||||
MixRGB<uint8>(pixels,y,nx,ny,w*h);
|
||||
|
||||
img.Create(w,h,3,IL_UNSIGNED_BYTE,pixels);
|
||||
|
||||
delete[] pixels;
|
||||
|
||||
if(img.SaveFile(out_filename))
|
||||
std_cout<<OS_TEXT("Output 1: ")<<out_filename.c_str()<<std::endl;
|
||||
}
|
||||
|
||||
if(metallic.isHas()&&roughness.isHas())
|
||||
{
|
||||
ILImage img;
|
||||
const OSString out_filename=OSString(argv[1])+OS_TEXT("_UVMR.png");
|
||||
|
||||
uint8 *pixels=new uint8[half_w*half_h*4];
|
||||
|
||||
MixRGBA<uint8>(pixels,u,v,metallic.GetLum(),roughness.GetLum(),half_w*half_h);
|
||||
|
||||
img.Create(half_w,half_h,4,IL_UNSIGNED_BYTE,pixels);
|
||||
|
||||
delete[] pixels;
|
||||
|
||||
if(img.SaveFile(out_filename))
|
||||
std_cout<<OS_TEXT("Output 2: ")<<out_filename.c_str()<<std::endl;
|
||||
}
|
||||
else
|
||||
if(metallic.isHas())
|
||||
{
|
||||
ILImage img;
|
||||
const OSString out_filename=OSString(argv[1])+OS_TEXT("_UVM.png");
|
||||
|
||||
uint8 *pixels=new uint8[half_w*half_h*3];
|
||||
|
||||
MixRGB<uint8>(pixels,u,v,metallic.GetLum(),half_w*half_h);
|
||||
|
||||
img.Create(half_w,half_h,3,IL_UNSIGNED_BYTE,pixels);
|
||||
|
||||
delete[] pixels;
|
||||
|
||||
if(img.SaveFile(out_filename))
|
||||
std_cout<<OS_TEXT("Output 2: ")<<out_filename.c_str()<<std::endl;
|
||||
}
|
||||
else
|
||||
if(roughness.isHas())
|
||||
{
|
||||
ILImage img;
|
||||
const OSString out_filename=OSString(argv[1])+OS_TEXT("_UVR.png");
|
||||
|
||||
uint8 *pixels=new uint8[half_w*half_h*3];
|
||||
|
||||
MixRGB<uint8>(pixels,u,v,roughness.GetLum(),half_w*half_h);
|
||||
|
||||
img.Create(half_w,half_h,3,IL_UNSIGNED_BYTE,pixels);
|
||||
|
||||
delete[] pixels;
|
||||
|
||||
if(img.SaveFile(out_filename))
|
||||
std_cout<<OS_TEXT("Output 2: ")<<out_filename.c_str()<<std::endl;
|
||||
}
|
||||
|
||||
delete[] y;
|
||||
delete[] u;
|
||||
delete[] v;
|
||||
delete[] nx;
|
||||
delete[] ny;
|
||||
|
||||
ilShutDown();
|
||||
return 0;
|
||||
}
|
||||
|
58
NormalTest.cpp
Normal file
58
NormalTest.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include<iostream>
|
||||
#include<ILImage.h>
|
||||
#include<hgl/type/DataType.h>
|
||||
#include<hgl/filesystem/FileSystem.h>
|
||||
|
||||
using namespace hgl;
|
||||
using namespace hgl::filesystem;
|
||||
|
||||
namespace hgl
|
||||
{
|
||||
void normal_compress(uint8 *x,uint8 *y,const uint8 *rgb,const uint count);
|
||||
void normal_decompress(uint8 *rgb,const uint8 *x,const uint8 *y,const uint count);
|
||||
}
|
||||
|
||||
#if HGL_OS == HGL_OS_Windows
|
||||
#define std_cout std::wcout
|
||||
|
||||
int wmain(int argc,wchar_t **argv)
|
||||
#else
|
||||
|
||||
#define std_cout std::cout
|
||||
int main(int argc,char **argv)
|
||||
#endif//
|
||||
{
|
||||
if(argc<1)
|
||||
return 0;
|
||||
|
||||
ilInit();
|
||||
|
||||
ILImage rgb_image;
|
||||
|
||||
if(!rgb_image.LoadFile(argv[1]))
|
||||
{
|
||||
std::cout<<"open source file failed!"<<std::endl;
|
||||
return(1);
|
||||
}
|
||||
|
||||
uint8 *rgb=(uint8 *)rgb_image.GetRGB(IL_UNSIGNED_BYTE);
|
||||
|
||||
const uint pixels=rgb_image.pixel_total();
|
||||
|
||||
uint8 *y=new uint8[pixels];
|
||||
uint8 *x=new uint8[pixels];
|
||||
|
||||
normal_compress(x,y,rgb,pixels);
|
||||
normal_decompress(rgb,x,y,pixels);
|
||||
|
||||
OSString filename;
|
||||
|
||||
filename=ClipFileMainname<os_char>(argv[1]);
|
||||
|
||||
filename+=OS_TEXT("_XY.png");
|
||||
|
||||
if(rgb_image.SaveFile(filename))
|
||||
std_cout<<OS_TEXT("Save To ")<<filename.c_str()<<OS_TEXT(" successed!")<<std::endl;
|
||||
|
||||
ilShutDown();
|
||||
}
|
61
SpheremapNormal.cpp
Normal file
61
SpheremapNormal.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include<hgl/type/DataType.h>
|
||||
#include<hgl/math/Vector.h>
|
||||
|
||||
/**
|
||||
* A_bit_more_deferred_-_CryEngine3
|
||||
|
||||
Normal to GBufffer:
|
||||
|
||||
G=normalize(N.xy)*sqrt(N.z*0.5+0.5)
|
||||
|
||||
GBuffer to Normal:
|
||||
|
||||
N.z=length2(G.xy)*2-1N.xy=normalize(G.xy)*sqrt(1-N.z*N.z)
|
||||
*/
|
||||
|
||||
namespace hgl
|
||||
{
|
||||
void normal_compress(uint8 *x,uint8 *y,const uint8 *rgb,const uint count)
|
||||
{
|
||||
Vector3f in;
|
||||
Vector2f in_xy;
|
||||
Vector2f out;
|
||||
|
||||
for(uint i=0;i<count;i++)
|
||||
{
|
||||
in.x=float(*rgb)/255.0f;++rgb;
|
||||
in.y=float(*rgb)/255.0f;++rgb;
|
||||
in.z=float(*rgb)/255.0f;++rgb;
|
||||
|
||||
in_xy=in.xy().Normalized();
|
||||
out=in_xy*sqrt(in.z*0.5+0.5);
|
||||
|
||||
*x=out.x*255;++x;
|
||||
*y=out.y*255;++y;
|
||||
}
|
||||
}
|
||||
|
||||
void normal_decompress(uint8 *rgb,const uint8 *x,const uint8 *y,const uint count)
|
||||
{
|
||||
Vector2f in;
|
||||
Vector2f in_normal;
|
||||
Vector3f out;
|
||||
float s;
|
||||
|
||||
for(uint i=0;i<count;i++)
|
||||
{
|
||||
in.x=(*x)/255.0f;++x;
|
||||
in.y=(*y)/255.0f;++y;
|
||||
|
||||
out.z=length(in)*2.0-1;
|
||||
in_normal=in.Normalized();
|
||||
s=sqrt(1-out.z*out.z);
|
||||
out.x=in_normal.x*s;
|
||||
out.y=in_normal.y*s;
|
||||
|
||||
*rgb=out.x*255;++rgb;
|
||||
*rgb=out.y*255;++rgb;
|
||||
*rgb=out.z*255;++rgb;
|
||||
}
|
||||
}
|
||||
}//namespace hgl
|
@ -12,6 +12,9 @@ namespace hgl
|
||||
void YUV2RGB(uint8 *rgb,const uint8 *y,const uint8 *u,const uint8 *v,const uint w,const uint h);
|
||||
|
||||
void InitYUV2RGBDecode();
|
||||
|
||||
void normal_compress(uint8 *x,uint8 *y,const uint8 *rgb,const uint count);
|
||||
void normal_decompress(uint8 *rgb,const uint8 *x,const uint8 *y,const uint count);
|
||||
}
|
||||
|
||||
#if HGL_OS == HGL_OS_Windows
|
||||
@ -57,7 +60,7 @@ int main(int argc,char **argv)
|
||||
|
||||
filename+=OS_TEXT("_YUV.png");
|
||||
|
||||
if(ilSaveImage(filename.c_str()))
|
||||
if(rgb_image.SaveFile(filename))
|
||||
std_cout<<OS_TEXT("Save To ")<<filename.c_str()<<OS_TEXT(" successed!")<<std::endl;
|
||||
|
||||
ilShutDown();
|
||||
|
Loading…
x
Reference in New Issue
Block a user